home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / xwindows / demos / xfract_1.z / xfract_1 / xfractint-1.06 / prompts.c < prev    next >
C/C++ Source or Header  |  1992-09-28  |  98KB  |  3,556 lines

  1. /*
  2.     Various routines that prompt for things.
  3.     This module is linked as an overlay, use ENTER_OVLY and EXIT_OVLY.
  4. */
  5.  
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <ctype.h>
  10. #ifndef XFRACT
  11. #include <dos.h>
  12. #else
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #include <sys/dir.h>
  16. #endif
  17. #ifdef __TURBOC__
  18. #include <alloc.h>
  19. #else
  20. #include <malloc.h>
  21. #endif
  22.  
  23. #ifdef __hpux
  24. #include <sys/param.h>
  25. #define getwd(a) getcwd(a,MAXPATHLEN)
  26. #endif
  27.  
  28. #include "fractint.h"
  29. #include "fractype.h"
  30. #include "helpdefs.h"
  31. #include "prototyp.h"
  32.  
  33. extern int Targa_Overlay;
  34. extern int Targa_Out;
  35. extern BYTE back_color[];
  36.  
  37. /* Routines in this module    */
  38.  
  39. static    int prompt_valuestring(char *buf,struct fullscreenvalues *val);
  40. static    int prompt_checkkey(int curkey);
  41. static    int input_field_list(int attr,char *fld,int vlen,char **list,int llen,
  42.                  int row,int col,int (*checkkey)(int));
  43. static    int select_fracttype(int t);
  44. static    int sel_fractype_help(int curkey, int choice);
  45. static    int get_corners(void);
  46. static    int edit_ifs_params(void );
  47. static    int select_type_params(int newfractype,int oldfractype);
  48. static    void set_default_parms(void);
  49. static    long get_file_entry(int,char *,char *,char *,char *);
  50. static    long gfe_choose_entry(int,char *,char *,char *);
  51. static    int check_gfe_key(int curkey,int choice);
  52. static    void load_entry_text(FILE *entfile,char far *buf,int maxlines);
  53. static    void format_parmfile_line(int,char *);
  54. static    int get_light_params(void );
  55. static    int check_mapfile(void );
  56. static    int get_funny_glasses_params(void );
  57. static    int findfirst(char *path);
  58. static    int findnext(void );
  59. static    int lccompare(VOIDCONSTPTR, VOIDCONSTPTR);
  60.     int splitpath(char *template,char *drive,char *dir,char *fname,char *ext);
  61. static    int makepath(char *template,char *drive,char *dir,char *fname,char *ext);
  62. static    void fix_dirname(char *dirname);
  63. static    int expand_dirname(char *dirname,char *drive);
  64. static    int filename_speedstr(int, int, int, char *, int);
  65. static    int isadirectory(char *s);
  66.  
  67. extern char *strig[];
  68. extern int numtrigfn;
  69. extern int bailout;
  70. extern int dotmode;
  71. extern int orbit_delay;
  72.  
  73. #ifndef XFRACT
  74. extern int strncasecmp(char *s,char *t,int ct);
  75. #endif
  76.  
  77. static char funnyglasses_map_name[16];
  78. extern char temp[], temp1[256];   /* temporary strings          */
  79. extern int mapset;
  80. extern int previewfactor;
  81. extern int xtrans, ytrans;
  82. extern int red_crop_left, red_crop_right;
  83. extern int blue_crop_left, blue_crop_right;
  84. extern int red_bright, blue_bright;
  85. extern char showbox; /* flag to show box and vector in preview */
  86. extern int debugflag;
  87. extern int extraseg;
  88. extern int whichimage;
  89. extern int xadjust;
  90. extern int eyeseparation;
  91. extern int glassestype;
  92. char   MAP_name[80] = "";
  93. int    mapset = 0;
  94. extern    int    overlay3d;        /* 3D overlay flag: 0 = OFF */
  95. extern    int    lookatmouse;
  96. extern    int haze;
  97. extern    int RANDOMIZE;
  98. extern    char light_name[];
  99. extern    int Ambient;
  100. extern    int RAY;
  101. extern    int BRIEF;
  102. extern    char ray_name[];
  103.  
  104. extern    int    init3d[20];    /* '3d=nn/nn/nn/...' values */
  105. extern    double    xxmin,xxmax;    /* initial corner values    */
  106. extern    double    yymin,yymax;    /* initial corner values    */
  107. extern    BYTE usemag;
  108.  
  109. extern    int AntiAliasing;
  110. extern double zzmin, zzmax, ttmin, ttmax;
  111. extern int Transparent3D;
  112.  
  113. extern    double    xx3rd,yy3rd;    /* initial corner values    */
  114. extern    int    invert;     /* non-zero if inversion active */
  115. extern    double    inversion[3];    /* radius, xcenter, ycenter */
  116. extern    long    fudge;        /* 2**fudgefactor    */
  117. extern    int    bitshift;    /* fudgefactor        */
  118. extern    double    param[4];    /* up to four parameters    */
  119. extern    int    pot16bit;
  120. extern    int    disk16bit;
  121. extern    double    potparam[3];    /* three potential parameters*/
  122. extern    int    fractype;    /* if == 0, use Mandelbrot  */
  123. extern    char    usr_floatflag;    /* floating-point fractals? */
  124. extern    int    maxit;        /* try this many iterations */
  125. extern    int    inside;     /* inside color */
  126. extern    int    fillcolor;     /* fill color */
  127. extern    int    outside;    /* outside color */
  128. extern    int    finattract;    /* finite attractor switch */
  129. extern    char    savename[80];    /* save files using this name */
  130. extern    char    ifsfilename[80];    /* IFS code file */
  131. extern    char    ifs3dfilename[80];  /* IFS 3D code file */
  132. extern    char    preview;    /* 3D preview mode flag */
  133. extern    int    decomp[];    /* decomposition parameters */
  134. extern    int    usr_distest;    /* distance estimator option */
  135. extern    int    distestwidth;
  136. extern    int    transparent[];    /* transparency values */
  137. extern    char    usr_stdcalcmode; /* '1', '2', 'g', 'b' */
  138. extern    char overwrite;     /* overwrite= flag */
  139. extern    int    soundflag;    /* sound option */
  140. extern    int    LogFlag;    /* non-zero if logarithmic palettes */
  141. extern    int    usr_biomorph;    /* Biomorph flag */
  142. extern    long    xmin, xmax, ymin, ymax; /* screen corner values */
  143. extern    int    calc_status;    /* calc status: complete, resumable, ... */
  144. extern    int    xdots, ydots;    /* coordinates of dots on the screen  */
  145. extern    int    colors;     /* maximum colors available */
  146. extern    int    row, col;
  147. extern    int    viewwindow;
  148. extern    float    viewreduction;
  149. extern    int    viewcrop;
  150. extern    float    finalaspectratio;
  151. extern    int    viewxdots,viewydots;
  152. extern    int    textcbase;
  153. extern    int    textrow,textcol;
  154. extern    int    resave_flag;    /* resaving after a timed save */
  155. extern    int    started_resaves;
  156. extern    char    boxy[];
  157. extern    char    *fkeys[];
  158. extern    int    kbdkeys[];
  159. extern    int    video_type;
  160. extern    int    adapter;
  161. extern    int    rotate_lo,rotate_hi;
  162. extern    int    display3d;
  163. extern    int    rangeslen;
  164.  
  165. extern  int  cmdarg(char *,int);
  166.  
  167. extern char LFileName[];    /* file to find the formulas in */
  168. extern char LName[];        /* Name of the Formula (if not null) */
  169. extern char FormFileName[];
  170. extern char FormName[];
  171. extern char IFSFileName[];
  172. extern char IFSName[];
  173. extern char CommandFile[];
  174. extern char CommandName[];
  175. extern float far *ifs_defn;
  176. extern int ifs_type;
  177. extern int ifs_changed;
  178.  
  179. /* fullscreen_choice options */
  180. #define CHOICERETURNKEY 1
  181. #define CHOICEMENU    2
  182. #define CHOICEHELP    4
  183.  
  184. /* speed key state values */
  185. #define MATCHING     0    /* string matches list - speed key mode */
  186. #define TEMPLATE    -2    /* wild cards present - buiding template */
  187. #define SEARCHPATH    -3    /* no match - building path search name */
  188.  
  189. #define   FILEATTR     0x37       /* File attributes; select all but volume labels */
  190. #define   HIDDEN     2
  191. #define   SYSTEM     4
  192. #define   SUBDIR     16
  193. #define   MAXNUMFILES     300
  194.  
  195. #define FILE_MAX_PATH  80
  196. #define FILE_MAX_DIR   80
  197. #define FILE_MAX_DRIVE  3
  198. #define FILE_MAX_FNAME  9
  199. #define FILE_MAX_EXT    5
  200.  
  201. struct                   /* Allocate DTA and define structure */
  202. {
  203.      char path[21];            /* DOS path and filespec */
  204.      char attribute;            /* File attributes wanted */
  205.      int  ftime;            /* File creation time */
  206.      int  fdate;            /* File creation date */
  207.      long size;             /* File size in bytes */
  208.      char filename[13];         /* Filename and extension */
  209. } DTA;                   /* Disk Transfer Area */
  210.  
  211. #define GETFORMULA 0
  212. #define GETLSYS    1
  213. #define GETIFS       2
  214. #define GETPARM    3
  215.  
  216. /* --------------------------------------------------------------------- */
  217. extern char s_iter[];
  218. extern char s_real[];
  219. extern char s_mult[];
  220. extern char s_sum[];
  221. extern char s_imag[];
  222. extern char s_zmag[];
  223. extern char s_bof60[];
  224. extern char s_bof61[];
  225. extern char s_maxiter[];
  226. extern char s_epscross[];
  227. extern char s_startrail[];
  228. extern char s_normal[];
  229. extern char s_period[];
  230.  
  231. extern char gifmask[];
  232. char ifsmask[13]     = {"*.ifs"};
  233. char formmask[13]    = {"*.frm"};
  234. char lsysmask[13]    = {"*.l"};
  235. char commandmask[13] = {"*.par"};
  236.  
  237. void prompts_overlay() { }    /* for restore_active_ovly */
  238.  
  239.  
  240. /* --------------------------------------------------------------------- */
  241.  
  242. static int promptfkeys;
  243.  
  244. int fullscreen_prompt(    /* full-screen prompting routine */
  245.     char *hdg,        /* heading, lines separated by \n */
  246.     int numprompts,     /* there are this many prompts (max) */
  247.     char far **prompts,     /* array of prompting pointers */
  248.     struct fullscreenvalues *values, /* array of values */
  249.     int options,        /* for future */
  250.     int fkeymask,        /* bit n on if Fn to cause return */
  251.     char far *extrainfo    /* extra info box to display, \n separated */
  252.     )
  253. {
  254.    char far *hdgscan;
  255.    int titlelines,titlewidth,titlerow;
  256.    int maxpromptwidth,maxfldwidth,maxcomment;
  257.    int boxrow,boxlines;
  258.    int boxcol,boxwidth;
  259.    int extralines,extrawidth,extrarow;
  260.    int instrrow;
  261.    int promptrow,promptcol,valuecol;
  262.    int curchoice;
  263.    int done, i, j;
  264.    int anyinput;
  265.    int savelookatmouse;
  266.    int curtype, curlen;
  267.    char buf[81];
  268. #ifndef XFRACT
  269. static char far instr1[]  = {"Use " UPARR " and " DNARR " to select values to change"};
  270. static char far instr2a[]  = {"Type in replacement value for selected field"};
  271. static char far instr2b[]  = {"Use " LTARR " or " RTARR " to change value of selected field"};
  272. #else
  273. /* Some compilers don't accept "a" "b", so we have to fill in UPARR ourself.  */
  274. static char far instr1[]  = {"Use up(K) and down(J) to select values to change"};
  275. static char far instr2a[]  = {"Type in replacement value for selected field"};
  276. static char far instr2b[]  = {"Use left(H) or right(L) to change value of selected field"};
  277. #endif
  278. static char far instr3a[] = {"Press ENTER when finished (or ESCAPE to back out)"};
  279. static char far instr3b[] = {"Press ENTER when finished, ESCAPE to back out, or F1 for help"};
  280. static char far instr0a[] = {"No changeable parameters; press ENTER to exit"};
  281. static char far instr0b[] = {"No changeable parameters; press ENTER to exit or F1 for help"};
  282.  
  283.    ENTER_OVLY(OVLY_PROMPTS);
  284.  
  285.    if (numprompts <= 0) {    /* ?? nothing to do! */
  286.       EXIT_OVLY;
  287.       return(0);
  288.       }
  289.    
  290.    savelookatmouse = lookatmouse;
  291.    lookatmouse = 0;
  292.    promptfkeys = fkeymask;
  293.    helptitle();                /* clear screen, display title line  */
  294.    setattr(1,0,C_PROMPT_BKGRD,24*80);  /* init rest of screen to background */
  295.  
  296.    hdgscan = hdg;               /* count title lines, find widest */
  297.    i = titlewidth = 0;
  298.    titlelines = 1;
  299.    while (*hdgscan) {
  300.       if (*(hdgscan++) == '\n') {
  301.      ++titlelines;
  302.      i = -1;
  303.      }
  304.       if (++i > titlewidth)
  305.      titlewidth = i;
  306.       }
  307.    extralines = extrawidth = i = 0;
  308.    if ((hdgscan = extrainfo))
  309.       if (*hdgscan == 0)
  310.      extrainfo = NULL;
  311.       else { /* count extra lines, find widest */
  312.      extralines = 3;
  313.      while (*hdgscan) {
  314.         if (*(hdgscan++) == '\n') {
  315.            if (extralines + numprompts + titlelines >= 20) {
  316.            *hdgscan = 0; /* full screen, cut off here */
  317.            break;
  318.            }
  319.            ++extralines;
  320.            i = -1;
  321.            }
  322.         if (++i > extrawidth)
  323.            extrawidth = i;
  324.         }
  325.      }
  326.  
  327.    /* work out vertical positioning */
  328.    i = numprompts + titlelines + extralines + 3; /* total rows required */
  329.    j = (25 - i) / 2;               /* top row of it all when centered */
  330.    j -= j / 4;                   /* higher is better if lots extra */
  331.    boxlines = numprompts;
  332.    titlerow = 1 + j;
  333.    promptrow = boxrow = titlerow + titlelines;
  334.    if (titlerow > 2) {               /* room for blank between title & box? */
  335.       --titlerow;
  336.       --boxrow;
  337.       ++boxlines;
  338.       }
  339.    instrrow = boxrow+boxlines;
  340.    if (instrrow + 3 + extralines < 25) {
  341.       ++boxlines;    /* blank at bottom of box */
  342.       ++instrrow;
  343.       if (instrrow + 3 + extralines < 25)
  344.      ++instrrow; /* blank before instructions */
  345.       }
  346.    extrarow = instrrow + 2;
  347.    if (numprompts > 1) /* 3 instructions lines */
  348.       ++extrarow;
  349.    if (extrarow + extralines < 25)
  350.       ++extrarow;
  351.  
  352.    /* work out horizontal positioning */
  353.    maxfldwidth = maxpromptwidth = maxcomment = anyinput = 0;
  354.    for (i = 0; i < numprompts; i++) {
  355.       if (values[i].type == 'y') {
  356.      static char *noyes[2] = {"no","yes"};
  357.      values[i].type = 'l';
  358.      values[i].uval.ch.vlen = 3;
  359.      values[i].uval.ch.list = noyes;
  360.      values[i].uval.ch.llen = 2;
  361.      }
  362.       j = far_strlen(prompts[i]);
  363.       if (values[i].type == '*') {
  364.      if (j > maxcomment)     maxcomment = j;
  365.      }
  366.       else {
  367.          anyinput = 1;
  368.      if (j > maxpromptwidth) maxpromptwidth = j;
  369.      j = prompt_valuestring(buf,&values[i]);
  370.      if (j > maxfldwidth)     maxfldwidth = j;
  371.      }
  372.       }
  373.    boxwidth = maxpromptwidth + maxfldwidth + 2;
  374.    if (maxcomment > boxwidth) boxwidth = maxcomment;
  375.    if ((boxwidth += 4) > 80) boxwidth = 80;
  376.    boxcol = (80 - boxwidth) / 2;       /* center the box */
  377.    promptcol = boxcol + 2;
  378.    valuecol = boxcol + boxwidth - maxfldwidth - 2;
  379.    if (boxwidth <= 76) {           /* make margin a bit wider if we can */
  380.       boxwidth += 2;
  381.       --boxcol;
  382.       }
  383.    if ((j = titlewidth) < extrawidth)
  384.       j = extrawidth;
  385.    if ((i = j + 4 - boxwidth) > 0) {   /* expand box for title/extra */
  386.       if (boxwidth + i > 80)
  387.      i = 80 - boxwidth;
  388.       boxwidth += i;
  389.       boxcol -= i / 2;
  390.       }
  391.    i = (90 - boxwidth) / 20;
  392.    boxcol    -= i;
  393.    promptcol -= i;
  394.    valuecol  -= i;
  395.  
  396.    /* display box heading */
  397.    for (i = titlerow; i < boxrow; ++i)
  398.       setattr(i,boxcol,C_PROMPT_HI,boxwidth);
  399.    textcbase = boxcol + (boxwidth - titlewidth) / 2;
  400.    putstring(titlerow,0,C_PROMPT_HI,hdg);
  401.  
  402.    /* display extra info */
  403.    if (extrainfo) {
  404. #ifndef XFRACT
  405. #define S1 '\xC4'
  406. #define S2 "\xC0"
  407. #define S3 "\xD9"
  408. #define S4 "\xB3"
  409. #define S5 "\xDA"
  410. #define S6 "\xBF"
  411. #else
  412. #define S1 '-'
  413. #define S2 "+" /* ll corner */
  414. #define S3 "+" /* lr corner */
  415. #define S4 "|"
  416. #define S5 "+" /* ul corner */
  417. #define S6 "+" /* ur corner */
  418. #endif
  419.       memset(buf,S1,80); buf[boxwidth-2] = 0;
  420.       textcbase = boxcol + 1;
  421.       putstring(extrarow,0,C_PROMPT_BKGRD,buf);
  422.       putstring(extrarow+extralines-1,0,C_PROMPT_BKGRD,buf);
  423.       --textcbase;
  424.       putstring(extrarow,0,C_PROMPT_BKGRD,S5);
  425.       putstring(extrarow+extralines-1,0,C_PROMPT_BKGRD,S2);
  426.       textcbase += boxwidth - 1;
  427.       putstring(extrarow,0,C_PROMPT_BKGRD,S6);
  428.       putstring(extrarow+extralines-1,0,C_PROMPT_BKGRD,S3);
  429.       textcbase = boxcol;
  430.       for (i = 1; i < extralines-1; ++i) {
  431.          putstring(extrarow+i,0,C_PROMPT_BKGRD,S4);
  432.          putstring(extrarow+i,boxwidth-1,C_PROMPT_BKGRD,S4);
  433.      }
  434.       textcbase += (boxwidth - extrawidth) / 2;
  435.       putstring(extrarow+1,0,C_PROMPT_TEXT,extrainfo);
  436.       }
  437.    textcbase = 0;
  438.  
  439.    /* display empty box */
  440.    for (i = 0; i < boxlines; ++i)
  441.       setattr(boxrow+i,boxcol,C_PROMPT_LO,boxwidth);
  442.  
  443.    /* display initial values */
  444.    for (i = 0; i < numprompts; i++) {
  445.       putstring(promptrow+i, promptcol, C_PROMPT_LO, prompts[i]);
  446.       prompt_valuestring(buf,&values[i]);
  447.       putstring(promptrow+i, valuecol, C_PROMPT_LO, buf);
  448.       }
  449.  
  450.    if (!anyinput) {
  451.       putstringcenter(instrrow,0,80,C_PROMPT_BKGRD,
  452.         (helpmode > 0) ? instr0b : instr0a);
  453.       movecursor(25,80);
  454.       while (1) {
  455.         while (!keypressed()) { }
  456.         done = getakey();
  457.         switch(done) {
  458.            case ESC:
  459.               done = -1;
  460.            case ENTER:
  461.            case ENTER_2:
  462.               goto fullscreen_exit;
  463.            case F2:
  464.            case F3:
  465.            case F4:
  466.            case F5:
  467.            case F6:
  468.            case F7:
  469.            case F8:
  470.            case F9:
  471.            case F10:
  472.               if (promptfkeys & (1<<(done+1-F1)) )
  473.                  goto fullscreen_exit;
  474.            }
  475.         }
  476.       }
  477.  
  478.  
  479.    /* display footing */
  480.    if (numprompts > 1)
  481.       putstringcenter(instrrow++,0,80,C_PROMPT_BKGRD,instr1);
  482.    putstringcenter(instrrow+1,0,80,C_PROMPT_BKGRD,
  483.      (helpmode > 0) ? instr3b : instr3a);
  484.  
  485.    curchoice = done = 0;
  486.    while (values[curchoice].type == '*') ++curchoice;
  487.  
  488.    while (!done) {
  489.  
  490.       curtype = values[curchoice].type;
  491.       curlen = prompt_valuestring(buf,&values[curchoice]);
  492.       putstringcenter(instrrow,0,80,C_PROMPT_BKGRD,
  493.               (curtype == 'l') ? instr2b : instr2a);
  494.       putstring(promptrow+curchoice,promptcol,C_PROMPT_HI,prompts[curchoice]);
  495.  
  496.       if (curtype == 'l') {
  497.      i = input_field_list(
  498.         C_PROMPT_CHOOSE, buf, curlen,
  499.         values[curchoice].uval.ch.list, values[curchoice].uval.ch.llen,
  500.         promptrow+curchoice,valuecol, prompt_checkkey);
  501.      for (j = 0; j < values[curchoice].uval.ch.llen; ++j)
  502.         if (strcmp(buf,values[curchoice].uval.ch.list[j]) == 0) break;
  503.      values[curchoice].uval.ch.val = j;
  504.      }
  505.       else {
  506.      j = 0;
  507.      if (curtype == 'i') j = 3;
  508.      if (curtype == 'd') j = 5;
  509.      if (curtype == 'D') j = 7;
  510.      if (curtype == 'f') j = 1;
  511.      i = input_field(j, C_PROMPT_INPUT, buf, curlen,
  512.         promptrow+curchoice,valuecol,prompt_checkkey);
  513.      switch (values[curchoice].type) {
  514.         case 'd':
  515.         case 'D':
  516.            values[curchoice].uval.dval = atof(buf);
  517.            break;
  518.         case 'f':
  519.            values[curchoice].uval.dval = atof(buf);
  520.            roundfloatd(&values[curchoice].uval.dval);
  521.            break;
  522.         case 'i':
  523.            values[curchoice].uval.ival = atoi(buf);
  524.            break;
  525.         case 's':
  526.            strncpy(values[curchoice].uval.sval,buf,16);
  527.            break;
  528.         default: /* assume 0x100+n */
  529.            strcpy(values[curchoice].uval.sbuf,buf);
  530.         }
  531.      }
  532.  
  533.       putstring(promptrow+curchoice,promptcol,C_PROMPT_LO,prompts[curchoice]);
  534.       j = strlen(buf);
  535.       memset(&buf[j],' ',80-j); buf[curlen] = 0;
  536.       putstring(promptrow+curchoice, valuecol, C_PROMPT_LO,  buf);
  537.  
  538.       switch(i) {
  539.      case 0:  /* enter  */
  540.         done = 13;
  541.         break;
  542.      case -1: /* escape */
  543.      case F2:
  544.      case F3:
  545.      case F4:
  546.      case F5:
  547.      case F6:
  548.      case F7:
  549.      case F8:
  550.      case F9:
  551.      case F10:
  552.         done = i;
  553.         break;
  554.      case PAGE_UP:
  555.         curchoice = -1;
  556.      case DOWN_ARROW:
  557.      case DOWN_ARROW_2:
  558.         do {
  559.            if (++curchoice >= numprompts) curchoice = 0;
  560.            } while (values[curchoice].type == '*');
  561.         break;
  562.      case PAGE_DOWN:
  563.         curchoice = numprompts;
  564.      case UP_ARROW:
  565.      case UP_ARROW_2:
  566.         do {
  567.            if (--curchoice < 0) curchoice = numprompts - 1;
  568.            } while (values[curchoice].type == '*');
  569.         break;
  570.      }
  571.       }
  572.  
  573. fullscreen_exit:
  574.    movecursor(25,80);
  575.    lookatmouse = savelookatmouse;
  576.    EXIT_OVLY;
  577.    return(done);
  578. }
  579.  
  580. static int prompt_valuestring(char *buf,struct fullscreenvalues *val)
  581. {  /* format value into buf, return field width */
  582.    int i,ret;
  583.    switch (val->type) {
  584.       case 'd':
  585.      ret = 20;
  586.      i = 15;
  587.      while (1) {
  588.         if (fractype == CELLULAR) roundfloats(&val->uval.dval);
  589.         sprintf(buf,"%.*g",i,val->uval.dval);
  590.         if (strlen(buf) <= ret) break;
  591.         --i;
  592.         }
  593.      break;
  594.       case 'D':
  595.      if (val->uval.dval<0) { /* We have to round the right way */
  596.          sprintf(buf,"%ld",(long)(val->uval.dval-.5));
  597.      }
  598.      else {
  599.          sprintf(buf,"%ld",(long)(val->uval.dval+.5));
  600.      }
  601.      ret = 20;
  602.      break;
  603.       case 'f':
  604.      sprintf(buf,"%.7g",val->uval.dval);
  605.      ret = 14;
  606.      break;
  607.       case 'i':
  608.      sprintf(buf,"%d",val->uval.ival);
  609.      ret = 6;
  610.      break;
  611.       case '*':
  612.      *buf = ret = 0;
  613.      break;
  614.       case 's':
  615.      strncpy(buf,val->uval.sval,16);
  616.      buf[15] = 0;
  617.      ret = 15;
  618.      break;
  619.       case 'l':
  620.      strcpy(buf,val->uval.ch.list[val->uval.ch.val]);
  621.      ret = val->uval.ch.vlen;
  622.      break;
  623.       default: /* assume 0x100+n */
  624.      strcpy(buf,val->uval.sbuf);
  625.      ret = val->type & 0xff;
  626.       }
  627.    return ret;
  628. }
  629.  
  630. static int prompt_checkkey(int curkey)
  631. {
  632.    switch(curkey) {
  633.       case PAGE_UP:
  634.       case DOWN_ARROW:
  635.       case DOWN_ARROW_2:
  636.       case PAGE_DOWN:
  637.       case UP_ARROW:
  638.       case UP_ARROW_2:
  639.      return(curkey);
  640.       case F2:
  641.       case F3:
  642.       case F4:
  643.       case F5:
  644.       case F6:
  645.       case F7:
  646.       case F8:
  647.       case F9:
  648.       case F10:
  649.      if (promptfkeys & (1<<(curkey+1-F1)) )
  650.         return(curkey);
  651.       }
  652.    return(0);
  653. }
  654.  
  655. static int input_field_list(
  656.     int attr,          /* display attribute */
  657.     char *fld,          /* display form field value */
  658.     int vlen,          /* field length */
  659.     char **list,          /* list of values */
  660.     int llen,          /* number of entries in list */
  661.     int row,          /* display row */
  662.     int col,          /* display column */
  663.     int (*checkkey)(int)  /* routine to check non data keys, or NULL */
  664.     )
  665. {
  666.    int initval,curval;
  667.    char buf[81];
  668.    int curkey;
  669.    int i, j;
  670.    int ret,savelookatmouse;
  671.    savelookatmouse = lookatmouse;
  672.    lookatmouse = 0;
  673.    for (initval = 0; initval < llen; ++initval)
  674.       if (strcmp(fld,list[initval]) == 0) break;
  675.    if (initval >= llen) initval = 0;
  676.    curval = initval;
  677.    ret = -1;
  678.    while (1) {
  679.       strcpy(buf,list[curval]);
  680.       i = strlen(buf);
  681.       while (i < vlen)
  682.      buf[i++] = ' ';
  683.       buf[vlen] = 0;
  684.       putstring(row,col,attr,buf);
  685.       curkey = keycursor(row,col); /* get a keystroke */
  686.       switch (curkey) {
  687.      case ENTER:
  688.      case ENTER_2:
  689.         ret = 0;
  690.         goto inpfldl_end;
  691.      case ESC:
  692.         goto inpfldl_end;
  693.      case RIGHT_ARROW:
  694.      case RIGHT_ARROW_2:
  695.         if (++curval >= llen)
  696.            curval = 0;
  697.         break;
  698.      case LEFT_ARROW:
  699.      case LEFT_ARROW_2:
  700.         if (--curval < 0)
  701.            curval = llen - 1;
  702.         break;
  703.      case F5:
  704.         curval = initval;
  705.         break;
  706.      default:
  707.             if (nonalpha(curkey)) {
  708.            if (checkkey && (ret = (*checkkey)(curkey)))
  709.           goto inpfldl_end;
  710.            break;                     /* non alphanum char */
  711.            }
  712.         j = curval;
  713.         for (i = 0; i < llen; ++i) {
  714.            if (++j >= llen)
  715.           j = 0;
  716.            if ((*list[j] & 0xdf) == (curkey & 0xdf)) {
  717.           curval = j;
  718.           break;
  719.           }
  720.            }
  721.      }
  722.       }
  723. inpfldl_end:
  724.    strcpy(fld,list[curval]);
  725.    lookatmouse = savelookatmouse;
  726.    return(ret);
  727. }
  728.  
  729.  
  730. /* --------------------------------------------------------------------- */
  731.  
  732. /* MCP 7-7-91, This is static code, but not called anywhere */
  733. #ifdef DELETE_UNUSED_CODE
  734.  
  735. /* compare for sort of type table */
  736. static int compare(const VOIDPTR i, const VOIDPTR j)
  737. {
  738.    return(strcmp(fractalspecific[(int)*((BYTE*)i)].name,
  739.            fractalspecific[(int)*((BYTE*)j)].name));
  740. }
  741.  
  742. /* --------------------------------------------------------------------- */
  743.  
  744. static void clear_line(int row, int start, int stop, int color) /* clear part of a line */
  745. {
  746.    int col;
  747.    for(col=start;col<= stop;col++)
  748.       putstring(row,col,color," ");
  749. }
  750.  
  751. #endif
  752.  
  753. /* --------------------------------------------------------------------- */
  754.  
  755. int get_fracttype()        /* prompt for and select fractal type */
  756. {
  757.    int done,i,oldfractype,t;
  758.    ENTER_OVLY(OVLY_PROMPTS);
  759.    done = -1;
  760.    oldfractype = fractype;
  761.    while (1) {
  762.       if ((t = select_fracttype(fractype)) < 0)
  763.      break;
  764.       if ((i = select_type_params(t, fractype)) == 0) { /* ok, all done */
  765.      done = 0;
  766.      break;
  767.      }
  768.       if (i > 0) /* can't return to prior image anymore */
  769.      done = 1;
  770.       }
  771.    if (done < 0)
  772.       fractype = oldfractype;
  773.    curfractalspecific = &fractalspecific[fractype];
  774.    EXIT_OVLY;
  775.    return(done);
  776. }
  777.  
  778. struct FT_CHOICE {
  779.       char name[15];
  780.       int  num;
  781.       };
  782. static struct FT_CHOICE **ft_choices; /* for sel_fractype_help subrtn */
  783.  
  784. static int select_fracttype(int t) /* subrtn of get_fracttype, separated */
  785.                    /* so that storage gets freed up     */
  786. {
  787.    int oldhelpmode;
  788.    int numtypes, done;
  789.    int i, j;
  790. #define MAXFTYPES 200
  791.    char tname[40];
  792.    struct FT_CHOICE *choices[MAXFTYPES];
  793.    int attributes[MAXFTYPES];
  794.  
  795.    /* steal existing array for "choices" */
  796.    choices[0] = (struct FT_CHOICE *)boxy;
  797.    attributes[0] = 1;
  798.    for (i = 1; i < MAXFTYPES; ++i) {
  799.       choices[i] = choices[i-1] + 1;
  800.       attributes[i] = 1;
  801.       }
  802.    ft_choices = &choices[0];
  803.  
  804.    /* setup context sensitive help */
  805.    oldhelpmode = helpmode;
  806.    helpmode = HELPFRACTALS;
  807.  
  808.    if (t == IFS3D) t = IFS;
  809.    i = j = -1;
  810.    while(fractalspecific[++i].name) {
  811.       if (fractalspecific[i].name[0] == '*')
  812.      continue;
  813.       strcpy(choices[++j]->name,fractalspecific[i].name);
  814.       choices[j]->name[14] = 0; /* safety */
  815.       choices[j]->num = i;    /* remember where the real item is */
  816.       }
  817.    numtypes = j + 1;
  818.    qsort(choices,numtypes,sizeof(char *),lccompare); /* sort list */
  819.    j = 0;
  820.    for (i = 0; i < numtypes; ++i) /* find starting choice in sorted list */
  821.       if (choices[i]->num == t || choices[i]->num == fractalspecific[t].tofloat)
  822.      j = i;
  823.  
  824.    tname[0] = 0;
  825.    done = fullscreen_choice(CHOICEHELP+8,"Select a Fractal Type",NULL,
  826.                 "Press F2 for a description of the highlighted type",
  827.                 numtypes,(char **)choices,attributes,0,0,0,j,
  828.                 NULL,tname,NULL,sel_fractype_help);
  829.    if (done >= 0)
  830.       done = choices[done]->num;
  831.    helpmode = oldhelpmode;
  832.    return(done);
  833. }
  834.  
  835. static int sel_fractype_help(int curkey,int choice)
  836. {
  837.    int oldhelpmode;
  838.    if (curkey == F2) {
  839.       oldhelpmode = helpmode;
  840.       helpmode = fractalspecific[(*(ft_choices+choice))->num].helptext;
  841.       help(0);
  842.       helpmode = oldhelpmode;
  843.       }
  844.    return(0);
  845. }
  846.  
  847. static int select_type_params(    /* prompt for new fractal type parameters */
  848.     int newfractype,    /* new fractal type */
  849.     int oldfractype     /* previous fractal type */
  850.     )
  851. {
  852.    int ret,oldhelpmode;
  853.  
  854.    oldhelpmode = helpmode;
  855.    ret = 0;
  856.    fractype = newfractype;
  857.    curfractalspecific = &fractalspecific[fractype];
  858.  
  859.    if (fractype == LSYSTEM) {
  860.       helpmode = HT_LSYS;
  861.       if (get_file_entry(GETLSYS,"L-System",lsysmask,LFileName,LName) < 0) {
  862.      ret = 1;
  863.      goto sel_type_exit;
  864.      }
  865.       }
  866.    if (fractype == FORMULA || fractype == FFORMULA) {
  867.       helpmode = HT_FORMULA;
  868.       if (get_file_entry(GETFORMULA,"Formula",formmask,FormFileName,FormName) < 0) {
  869.      ret = 1;
  870.      goto sel_type_exit;
  871.      }
  872.       }
  873.    if (fractype == IFS || fractype == IFS3D) {
  874.       static char far ifsmsg[] = {
  875. #ifndef XFRACT
  876.          "Current IFS parameters have been edited but not saved.\n"
  877.          "Continue to replace them with new selection, cancel to keep them."};
  878. #else
  879.          "Current IFS parameters have been edited but not saved.\n\
  880. Continue to replace them with new selection, cancel to keep them."};
  881. #endif
  882.       helpmode = HT_IFS;
  883.       if (!ifs_defn || !ifs_changed || !stopmsg(22,ifsmsg))
  884.      if (get_file_entry(GETIFS,"IFS",ifsmask,IFSFileName,IFSName) < 0) {
  885.         ret = 1;
  886.         goto sel_type_exit;
  887.         }
  888.       }
  889.  
  890. /* Added the following to accommodate fn bifurcations.  JCO 7/2/92 */
  891.    if(((fractype == BIFURCATION) || (fractype == LBIFURCATION)) &&
  892.      !((oldfractype == BIFURCATION) || (oldfractype == LBIFURCATION)))
  893.         set_trig_array(0,"ident");
  894.    if(((fractype == BIFSTEWART) || (fractype == LBIFSTEWART)) &&
  895.      !((oldfractype == BIFSTEWART) || (oldfractype == LBIFSTEWART)))
  896.         set_trig_array(0,"ident");
  897.    if(((fractype == BIFLAMBDA) || (fractype == LBIFLAMBDA)) &&
  898.      !((oldfractype == BIFLAMBDA) || (oldfractype == LBIFLAMBDA)))
  899.         set_trig_array(0,"ident");
  900.    if(((fractype == BIFEQSINPI) || (fractype == LBIFEQSINPI)) &&
  901.      !((oldfractype == BIFEQSINPI) || (oldfractype == LBIFEQSINPI)))
  902.         set_trig_array(0,"sin");
  903.    if(((fractype == BIFADSINPI) || (fractype == LBIFADSINPI)) &&
  904.      !((oldfractype == BIFADSINPI) || (oldfractype == LBIFADSINPI)))
  905.         set_trig_array(0,"sin");
  906.  
  907.    set_default_parms();
  908.  
  909.    if (get_fract_params(0) < 0)
  910.       ret = 1;
  911.    else {
  912.       if (newfractype != oldfractype) {
  913.      invert = 0;
  914.      inversion[0] = inversion[1] = inversion[2] = 0;
  915.      }
  916.       }
  917.  
  918. sel_type_exit:
  919.    helpmode = oldhelpmode;
  920.    return(ret);
  921.  
  922. }
  923.  
  924. static void set_default_parms()
  925. {
  926.    int i;
  927.    xxmin = curfractalspecific->xmin;
  928.    xxmax = curfractalspecific->xmax;
  929.    yymin = curfractalspecific->ymin;
  930.    yymax = curfractalspecific->ymax;
  931.    xx3rd = xxmin;
  932.    yy3rd = yymin;
  933.    if (viewcrop && finalaspectratio != SCREENASPECT)
  934.       aspectratio_crop(SCREENASPECT,finalaspectratio);
  935.    for (i = 0; i < 4; i++) {
  936.       param[i] = curfractalspecific->paramvalue[i];
  937.       if (fractype == CELLULAR)  /* We need more digits displayed */
  938.          roundfloats(¶m[i]);
  939.       else
  940.          roundfloatd(¶m[i]);
  941.    }
  942. }
  943.  
  944.  
  945. /* --------------------------------------------------------------------- */
  946.  
  947. int get_fract_params(int caller)    /* prompt for type-specific parms */
  948. {
  949.    int i,j,k;
  950.    int curtype,numparams,numtrig;
  951.    struct fullscreenvalues paramvalues[12];
  952.    char far *choices[12];
  953.    int oldbailout;
  954.    int promptnum;
  955.    char msg[120];
  956.    char *typename, *tmpptr;
  957.    char bailoutmsg[50];
  958.    int ret = 0;
  959.    int oldhelpmode;
  960.    static char far t1[] = {"First Function"};
  961.    static char far t2[] = {"Second Function"};
  962.    static char far t3[] = {"Third Function"};
  963.    static char far t4[] = {"Fourth Function"};
  964.    static char far *trg[] = {t1, t2, t3, t4};
  965.    extern char tstack[4096];
  966.    char *filename,*entryname;
  967.    FILE *entryfile;
  968.    char *trignameptr[25];
  969.  
  970.    ENTER_OVLY(OVLY_PROMPTS);
  971.  
  972.    curtype = fractype;
  973.    if (curfractalspecific->name[0] == '*'
  974.      && (i = fractalspecific->tofloat) != NOFRACTAL
  975.      && fractalspecific[i].name[0] != '*')
  976.       curtype = i;
  977.    curfractalspecific = &fractalspecific[curtype];
  978.  
  979.    if (curtype == IFS || curtype == IFS3D) {
  980.       ret = ((caller) ? edit_ifs_params() : 0);
  981.       goto gfp_exit;
  982.       }
  983.  
  984.    if (*(typename = curfractalspecific->name) == '*')
  985.       ++typename;
  986.  
  987.    for (numparams = 0; numparams < 4; numparams++) {
  988.       if (curfractalspecific->param[numparams][0] == 0) break;
  989.       choices[numparams] = curfractalspecific->param[numparams];
  990.       paramvalues[numparams].type = 'd';
  991.  
  992.       if (choices[numparams][0] == '+') {
  993.       choices[numparams]++;
  994.       paramvalues[numparams].type = 'D';
  995.       }
  996.       paramvalues[numparams].uval.dval = param[numparams];
  997.       }
  998.  
  999.    numtrig = (curfractalspecific->flags >> 6) & 7;
  1000.    if(curtype==FORMULA || curtype==FFORMULA ) {
  1001.       extern char maxfn;
  1002.       numtrig = maxfn;
  1003.       }
  1004.    promptnum = numparams;
  1005.  
  1006.    if ((i = numtrigfn) > 27) i = 27;
  1007.    while (--i >= 0)
  1008.       trignameptr[i] = trigfn[i].name;
  1009.    for (i = 0; i < numtrig; i++) {
  1010.       paramvalues[promptnum].type = 'l';
  1011.       paramvalues[promptnum].uval.ch.val  = trigndx[i];
  1012.       paramvalues[promptnum].uval.ch.llen = numtrigfn;
  1013.       paramvalues[promptnum].uval.ch.vlen = 6;
  1014.       paramvalues[promptnum].uval.ch.list = trignameptr;
  1015.       choices[promptnum] = trg[i];
  1016.       ++promptnum;
  1017.       }
  1018.  
  1019.    if (curfractalspecific->orbit_bailout)
  1020.       if (potparam[0] != 0.0 && potparam[2] != 0.0) {
  1021.      paramvalues[promptnum].type = '*';
  1022.      choices[promptnum] = "Bailout: continuous potential (Y screen) value in use";
  1023.      ++promptnum;
  1024.      }
  1025.       else {
  1026.       static char far bailoutstr[] = {"Bailout value (0 means use default)"};
  1027.      choices[promptnum] = bailoutstr;
  1028.      paramvalues[promptnum].type = 'i';
  1029.      paramvalues[promptnum].uval.ival = oldbailout = bailout;
  1030.      ++promptnum;
  1031.      paramvalues[promptnum].type = '*';
  1032.      i = curfractalspecific->orbit_bailout;
  1033.      tmpptr = typename;
  1034.      if (usr_biomorph != -1) {
  1035.         i = 100;
  1036.         tmpptr = "biomorph";
  1037.         }
  1038.      sprintf(bailoutmsg,"    (%s default is %d)",tmpptr,i);
  1039.      choices[promptnum] = bailoutmsg;
  1040.      ++promptnum;
  1041.      }
  1042.  
  1043.    if (caller                /* <z> command ? */
  1044.       && (display3d > 0 || promptnum == 0)) {
  1045.        static char far msg[]={"Current type has no type-specific parameters"};
  1046.        stopmsg(20,msg);
  1047.        goto gfp_exit;
  1048.        }
  1049.  
  1050.    /* note: max of 9 prompt lines now, plus hdgs & instr of course */
  1051.  
  1052.    tstack[0] = 0;
  1053.    if ((i = curfractalspecific->helpformula) < -1) {
  1054.       if (i == -2) { /* special for formula */
  1055.      filename = FormFileName;
  1056.      entryname = FormName;
  1057.      }
  1058.       else {     /* -3, special for lsystem */
  1059.      filename = LFileName;
  1060.      entryname = LName;
  1061.      }
  1062.       if (find_file_item(filename,entryname,&entryfile) == 0) {
  1063.      load_entry_text(entryfile,tstack,16);
  1064.      fclose(entryfile);
  1065.      }
  1066.       }
  1067.    else if (i >= 0) {
  1068.       int c,lines;
  1069.       if (i = read_help_topic(i,0,2000,tstack) > 0) i = 0;
  1070.       tstack[2000-i] = 0;
  1071.       i = j = lines = 0; k = 1;
  1072.       while ((c = tstack[i++])) {
  1073.      /* stop at ctl, blank, or line with col 1 nonblank, max 16 lines */
  1074.      if (k && c == ' ' && ++k <= 5) { } /* skip 4 blanks at start of line */
  1075.      else {
  1076.         if (c == '\n') {
  1077.            if (k) break; /* blank line */
  1078.            if (++lines >= 16) break;
  1079.            k = 1;
  1080.            }
  1081.         else if (c < 16) /* a special help format control char */
  1082.            break;
  1083.         else {
  1084.            if (k == 1) /* line starts in column 1 */
  1085.           break;
  1086.            k = 0;
  1087.            }
  1088.         tstack[j++] = c;
  1089.         }
  1090.      }
  1091.       while (--j >= 0 && tstack[j] == '\n') { }
  1092.       tstack[j+1] = 0;
  1093.       }
  1094.  
  1095.    sprintf(msg,
  1096.        "Parameters for fractal type %s\n(Press F6 for corner parameters)",
  1097.        typename);
  1098.    while (1) {
  1099.       oldhelpmode = helpmode;
  1100.       helpmode = curfractalspecific->helptext;
  1101.       i = fullscreen_prompt(msg,promptnum,choices,paramvalues,0,0x40,tstack);
  1102.       helpmode = oldhelpmode;
  1103.       if (i < 0) {
  1104.      if (ret == 0)
  1105.         ret = -1;
  1106.      goto gfp_exit;
  1107.      }
  1108.       if (i != F6) break;
  1109.       if (get_corners() > 0)
  1110.      ret = 1;
  1111.       }
  1112.  
  1113.    for ( i = 0; i < numparams; i++) {
  1114.       if (param[i] != paramvalues[i].uval.dval) {
  1115.      param[i] = paramvalues[i].uval.dval;
  1116.      ret = 1;
  1117.      }
  1118.       }
  1119.  
  1120.    for ( i = 0; i < numtrig; i++) {
  1121.       j = numparams + i;
  1122.       if (paramvalues[j].uval.ch.val != trigndx[i]) {
  1123.      set_trig_array(i,trigfn[paramvalues[j].uval.ch.val].name);
  1124.      ret = 1;
  1125.      }
  1126.       }
  1127.  
  1128.    if ((potparam[0] == 0.0 || potparam[2] == 0.0)
  1129.      && curfractalspecific->orbit_bailout) {
  1130.       bailout = paramvalues[numparams+numtrig].uval.ival;
  1131. #ifndef XFRACT
  1132.       if (bailout != 0 && (bailout < 4 || bailout > 32000))
  1133. #else /* We have big integers, so why not allow big bailouts? */
  1134.       if (bailout != 0 && (bailout < 4))
  1135. #endif
  1136.      bailout = oldbailout;
  1137.       if (bailout != oldbailout)
  1138.      ret = 1;
  1139.       }
  1140.  
  1141. gfp_exit:
  1142.    curfractalspecific = &fractalspecific[fractype];
  1143.    EXIT_OVLY;
  1144.    return(ret);
  1145. }
  1146.  
  1147. /* --------------------------------------------------------------------- */
  1148.  
  1149.    static FILE *gfe_file;
  1150.  
  1151. static long get_file_entry(int type,char *title,char *fmask,
  1152.               char *filename,char *entryname)
  1153. {
  1154.    /* Formula, LSystem, etc type structure, select from file */
  1155.    /* containing definitions in the form    name { ... }     */
  1156.    int newfile,firsttry;
  1157.    long entry_pointer;
  1158.    extern char tstack[4096];
  1159.    newfile = 0;
  1160.    while (1) {
  1161.       firsttry = 0;
  1162.       /* pb: binary mode used here - it is more work, but much faster, */
  1163.       /*     especially when ftell or fgetpos is used               */
  1164.       while (newfile || (gfe_file = fopen(filename, "rb")) == NULL) {
  1165.      char buf[60];
  1166.      newfile = 0;
  1167.      if (firsttry) {
  1168.         extern char s_cantfind[];
  1169.         sprintf(temp1,s_cantfind, filename);
  1170.         stopmsg(0,temp1);
  1171.         }
  1172.      sprintf(buf,"Select %s File",title);
  1173.      if (getafilename(buf,fmask,filename) < 0)
  1174.         return -1;
  1175.      firsttry = 1; /* if around open loop again it is an error */
  1176.      }
  1177.       setvbuf(gfe_file,tstack,_IOFBF,4096); /* improves speed when file is big */
  1178.       newfile = 0;
  1179.       if ((entry_pointer = gfe_choose_entry(type,title,filename,entryname)) == -2) {
  1180.      newfile = 1; /* go to file list, */
  1181.      continue;    /* back to getafilename */
  1182.      }
  1183.       if (entry_pointer == -1)
  1184.      return -1;
  1185.       switch (type) {
  1186.      case GETFORMULA:
  1187.         if (RunForm(entryname) == 0) return 0;
  1188.         break;
  1189.      case GETLSYS:
  1190.         if (LLoad() == 0) return 0;
  1191.         break;
  1192.      case GETIFS:
  1193.         if (ifsload() == 0) {
  1194.            fractype = (ifs_type == 0) ? IFS : IFS3D;
  1195.            curfractalspecific = &fractalspecific[fractype];
  1196.            set_default_parms(); /* to correct them if 3d */
  1197.            return 0;
  1198.            }
  1199.         break;
  1200.      case GETPARM:
  1201.         return entry_pointer;
  1202.      }
  1203.       }
  1204. }
  1205.  
  1206.    struct entryinfo {
  1207.       char name[ITEMNAMELEN+1];
  1208.       long point; /* points to the ( or the { following the name */
  1209.       };
  1210.    static struct entryinfo **gfe_choices; /* for format_getparm_line */
  1211.    static char *gfe_title;
  1212.  
  1213. static long gfe_choose_entry(int type,char *title,char *filename,char *entryname)
  1214. /* subrtn of get_file_entry, separated so that storage gets freed up */
  1215. {
  1216. #define MAXENTRIES 200
  1217.    int numentries, i;
  1218.    char buf[101];
  1219.    struct entryinfo *choices[MAXENTRIES];
  1220.    int attributes[MAXENTRIES];
  1221.    void (*formatitem)();
  1222.    int boxwidth,boxdepth,colwidth;
  1223.    long file_offset,name_offset;
  1224.    extern struct entryinfo boxx[MAXENTRIES];
  1225.  
  1226.    gfe_choices = &choices[0];
  1227.    gfe_title = title;
  1228.    for (i = 0; i < MAXENTRIES; i++) {
  1229.       attributes[i] = 1;
  1230.       choices[i] = &boxx[i];
  1231.       }
  1232.    numentries = 0;
  1233.    file_offset = -1;
  1234.  
  1235.    helptitle(); /* to display a clue when file big and next is slow */
  1236.  
  1237.    while (1) { /* scan the file for entry names */
  1238.       int c,len;
  1239.       do {
  1240.      ++file_offset;
  1241.      c = getc(gfe_file);
  1242.      } while (c == ' ' /* skip white space */
  1243.            || c == '\t' || c == '\n' || c == '\r');
  1244.       if (c == ';') {
  1245.      do {
  1246.         ++file_offset;
  1247.         c = getc(gfe_file);
  1248.         } while (c != '\n' && c != EOF && c != '\032');
  1249.      if (c == EOF || c == '\032') break;
  1250.      continue;
  1251.      }
  1252.       name_offset = file_offset;
  1253.       len = 0; /* next equiv roughly to fscanf(..,"%40[^ \n\r\t({\032]",buf) */
  1254.       while (c != ' ' && c != '\t' && c != '('
  1255.     && c != '{' && c != '\n' && c != '\r' && c != EOF && c != '\032') {
  1256.      if (len < 40) buf[len++] = c;
  1257.      c = getc(gfe_file);
  1258.      ++file_offset;
  1259.      }
  1260.       buf[len] = 0;
  1261.       while (c != '{' && c != '\n' && c != '\r' && c != EOF && c != '\032') {
  1262.      c = getc(gfe_file);
  1263.      ++file_offset;
  1264.      }
  1265.       if (c == '{') {
  1266.      while (c != '}' && c != EOF && c != '\032') {
  1267.         c = getc(gfe_file);
  1268.         ++file_offset;
  1269.         }
  1270.      if (c != '}') break;
  1271.      buf[ITEMNAMELEN] = 0;
  1272.      if (buf[0] != 0 && stricmp(buf,"comment") != 0) {
  1273.         strcpy(boxx[numentries].name,buf);
  1274.         boxx[numentries].point = name_offset;
  1275.         if (++numentries >= MAXENTRIES) {
  1276.            sprintf(buf,"Too many entries in file, first %d used",MAXENTRIES);
  1277.            stopmsg(0,buf);
  1278.            break;
  1279.            }
  1280.         }
  1281.      }
  1282.       else
  1283.      if (c == EOF || c == '\032') break;
  1284.       }
  1285.  
  1286.    if (numentries == 0) {
  1287.       static char far msg[]={"File doesn't contain any valid entries"};
  1288.       stopmsg(0,msg);
  1289.       fclose(gfe_file);
  1290.       return -2; /* back to file list */
  1291.       }
  1292.  
  1293.    qsort((char **)choices,numentries,sizeof(char *),lccompare);
  1294.  
  1295.    strcpy(buf,entryname); /* preset to last choice made */
  1296.    sprintf(temp1,"%s Selection\nFile: %s",title,filename);
  1297.    formatitem = NULL;
  1298.    boxwidth = colwidth = boxdepth = 0;
  1299.    if (type == GETPARM) {
  1300.       formatitem = format_parmfile_line;
  1301.       boxwidth = 1;
  1302.       boxdepth = 16;
  1303.       colwidth = 76;
  1304.       }
  1305.    i = fullscreen_choice(8,temp1,NULL,
  1306.       "Press F6 to select different file, F2 for details of highlighted choice",
  1307.                numentries,(char **)choices,attributes,
  1308.                boxwidth,boxdepth,colwidth,0,
  1309.                formatitem,buf,NULL,check_gfe_key);
  1310.    fclose(gfe_file);
  1311.    if (i < 0) {
  1312.       if (i == 0-F6)
  1313.      return -2; /* go back to file list */
  1314.       return -1;    /* cancel */
  1315.       }
  1316.    strcpy(entryname, choices[i]->name);
  1317.    return(choices[i]->point);
  1318. }
  1319.  
  1320. static int check_gfe_key(int curkey,int choice)
  1321. {
  1322.    char infhdg[60];
  1323.    char far *infbuf;
  1324.  
  1325.    if (curkey == F6)
  1326.       return 0-F6;
  1327.    if (curkey == F2) {
  1328.       infbuf = MK_FP(extraseg,0);
  1329.       fseek(gfe_file,gfe_choices[choice]->point,SEEK_SET);
  1330.       load_entry_text(gfe_file,infbuf,16);
  1331.       strcpy(infhdg,gfe_title);
  1332.       strcat(infhdg," file entry:\n\n");
  1333.  /* ... instead, call help with buffer?  heading added */
  1334.       stackscreen();
  1335.       helptitle();
  1336.       setattr(1,0,C_GENERAL_MED,24*80);
  1337.       putstring(2,1,C_GENERAL_HI,infhdg);
  1338.       textcbase = 2; /* left margin is 2 */
  1339.       putstring(-1,0,C_GENERAL_MED,infbuf);
  1340.       putstring(-1,0,C_GENERAL_LO,"\n\n\nPress any key to return to selection list");
  1341.       textcbase = 0;
  1342.       movecursor(25,80);
  1343.       getakeynohelp();
  1344.       unstackscreen();
  1345.       }
  1346.    return 0;
  1347. }
  1348.  
  1349. static void load_entry_text(FILE *entfile,char far *buf,int maxlines)
  1350. {
  1351.    int linect,linelen,c;
  1352.    linect = linelen = 0;
  1353.    while ((c = fgetc(entfile)) != EOF && c != '\032') {
  1354.       if (c != '\r') {
  1355.      if (c == '\t') {
  1356.         while ((linelen % 8) != 7 && linelen < 75) { /* 76 wide max */
  1357.            *(buf++) = ' ';
  1358.            ++linelen;
  1359.            }
  1360.         c = ' ';
  1361.         }
  1362.      if (c == '\n') {
  1363.         if (++linect > maxlines) break;
  1364.         linelen = -1;
  1365.         }
  1366.      if (++linelen > 75) {
  1367.         if (linelen == 76) *(buf++) = '\021';
  1368.         }
  1369.      else
  1370.         *(buf++) = c;
  1371.      if (c == '}') break;
  1372.      }
  1373.       }
  1374.    *buf = 0;
  1375. }
  1376.  
  1377. static void format_parmfile_line(int choice,char *buf)
  1378. {
  1379.    int c,i;
  1380.    char line[80];
  1381.    fseek(gfe_file,gfe_choices[choice]->point,SEEK_SET);
  1382.    while (getc(gfe_file) != '{') { }
  1383.    while ((c = getc(gfe_file)) == ' ' || c == '\t' || c == ';') { }
  1384.    i = 0;
  1385.    while (i < 56 && c != '\n' && c != '\r' && c != EOF && c != '\032') {
  1386.       line[i++] = (c == '\t') ? ' ' : c;
  1387.       c = getc(gfe_file);
  1388.       }
  1389.    line[i] = 0;
  1390.    sprintf(buf,"%-20s%-56s",gfe_choices[choice]->name,line);
  1391. }
  1392.  
  1393. /* --------------------------------------------------------------------- */
  1394.  
  1395. int get_fract3d_params() /* prompt for 3D fractal parameters */
  1396. {
  1397.    int i,k,ret,oldhelpmode;
  1398.    static char far p1[] = {"X-axis rotation in degrees"};
  1399.    static char far p2[] = {"Y-axis rotation in degrees"};
  1400.    static char far p3[] = {"Z-axis rotation in degrees"};
  1401.    static char far p4[] = {"Perspective distance [1 - 999, 0 for no persp]"};
  1402.    static char far p5[] = {"X shift with perspective (positive = right)"};
  1403.    static char far p6[] = {"Y shift with perspective (positive = up   )"};
  1404.    static char far p7[] = {"Stereo (R/B 3D)? (0=no,1=alternate,2=superimpose,3=photo)"};
  1405.    static char far *ifs3d_prompts[8] = {p1, p2, p3, p4, p5, p6, p7};
  1406.    struct fullscreenvalues uvalues[20];
  1407.  
  1408.    ENTER_OVLY(OVLY_PROMPTS);
  1409.    stackscreen();
  1410.  
  1411.    k = 0;
  1412.    uvalues[k].type = 'i';
  1413.    uvalues[k++].uval.ival = XROT;
  1414.    uvalues[k].type = 'i';
  1415.    uvalues[k++].uval.ival = YROT;
  1416.    uvalues[k].type = 'i';
  1417.    uvalues[k++].uval.ival = ZROT;
  1418.    uvalues[k].type = 'i';
  1419.    uvalues[k++].uval.ival = ZVIEWER;
  1420.    uvalues[k].type = 'i';
  1421.    uvalues[k++].uval.ival = XSHIFT;
  1422.    uvalues[k].type = 'i';
  1423.    uvalues[k++].uval.ival = YSHIFT;
  1424.    uvalues[k].type = 'i';
  1425.    uvalues[k++].uval.ival = glassestype;
  1426.  
  1427.    oldhelpmode = helpmode;
  1428.    helpmode = HELP3DFRACT;
  1429.    i = fullscreen_prompt("3D Parameters",k,ifs3d_prompts,uvalues,0,0,NULL);
  1430.    helpmode = oldhelpmode;
  1431.    if (i < 0) {
  1432.       ret = -1;
  1433.       goto get_f3d_exit;
  1434.       }
  1435.  
  1436.    ret = k = 0;
  1437.    XROT    =  uvalues[k++].uval.ival;
  1438.    YROT    =  uvalues[k++].uval.ival;
  1439.    ZROT    =  uvalues[k++].uval.ival;
  1440.    ZVIEWER =  uvalues[k++].uval.ival;
  1441.    XSHIFT  =  uvalues[k++].uval.ival;
  1442.    YSHIFT  =  uvalues[k++].uval.ival;
  1443.    glassestype = uvalues[k++].uval.ival;
  1444.    if (glassestype < 0 || glassestype > 3) glassestype = 0;
  1445.    if (glassestype)
  1446.       if (get_funny_glasses_params() || check_mapfile())
  1447.      ret = -1;
  1448.  
  1449. get_f3d_exit:
  1450.    unstackscreen();
  1451.    EXIT_OVLY;
  1452.    return(ret);
  1453. }
  1454.  
  1455. /* --------------------------------------------------------------------- */
  1456. /* These macros streamline the "save near space" campaign */ 
  1457.  
  1458. #define LOADPROMPTS3D(X)     {\
  1459.    static char far tmp[] = { X };\
  1460.    prompts3d[++k]= tmp;\
  1461.    }
  1462.  
  1463.  
  1464. int get_3d_params()    /* prompt for 3D parameters */
  1465. {
  1466.    char *choices[10];
  1467.    int attributes[21];
  1468.    int sphere;
  1469.    char *s;
  1470.    char far *prompts3d[21];
  1471.    struct fullscreenvalues uvalues[21];
  1472.    int i, k;
  1473.    int oldhelpmode;
  1474.  
  1475.    ENTER_OVLY(OVLY_PROMPTS);
  1476.  
  1477. #ifdef WINFRACT
  1478.      {
  1479.      extern int far wintext_textmode;
  1480.     
  1481.      if (wintext_textmode != 2)  /* are we in textmode? */
  1482.          return(0);              /* no - prompts are already handled */
  1483.      }
  1484. #endif
  1485. restart_1:
  1486.     if (Targa_Out && overlay3d)
  1487.         Targa_Overlay = 1;
  1488.  
  1489.    k= -1;
  1490.  
  1491.    LOADPROMPTS3D("Preview Mode?");
  1492.    uvalues[k].type = 'y';
  1493.    uvalues[k].uval.ch.val = preview;
  1494.  
  1495.    LOADPROMPTS3D("    Show Box?");
  1496.    uvalues[k].type = 'y';
  1497.    uvalues[k].uval.ch.val = showbox;
  1498.    
  1499.    LOADPROMPTS3D("Coarseness, preview/grid/ray (in y dir)");
  1500.    uvalues[k].type = 'i';
  1501.    uvalues[k].uval.ival = previewfactor;
  1502.  
  1503.    LOADPROMPTS3D("Spherical Projection?");
  1504.    uvalues[k].type = 'y';
  1505.    uvalues[k].uval.ch.val = sphere = SPHERE;
  1506.  
  1507.    LOADPROMPTS3D("Stereo (R/B 3D)? (0=no,1=alternate,2=superimpose,3=photo)");
  1508.    uvalues[k].type = 'i';
  1509.    uvalues[k].uval.ival = glassestype;
  1510.  
  1511.    LOADPROMPTS3D("Ray trace out? (0=No, 1=DKB/POVRay, 2=VIVID, 3=RAW,");
  1512.    uvalues[k].type = 'i';
  1513.    uvalues[k].uval.ival = RAY;
  1514.  
  1515.    LOADPROMPTS3D("                4=MTV, 5=RAYSHADE, 6=ACROSPIN, 7=DXF)");
  1516.    uvalues[k].type = '*';
  1517.  
  1518.    LOADPROMPTS3D("    Brief output?");
  1519.    uvalues[k].type = 'y';
  1520.    uvalues[k].uval.ch.val = BRIEF;
  1521.  
  1522.    check_writefile(ray_name,".ray");
  1523.    LOADPROMPTS3D("    Output File Name");
  1524.    uvalues[k].type = 's';
  1525.    strcpy(uvalues[k].uval.sval,ray_name);
  1526.  
  1527.    LOADPROMPTS3D("Targa output?");
  1528.    uvalues[k].type = 'y';
  1529.    uvalues[k].uval.ch.val = Targa_Out;
  1530.  
  1531.    oldhelpmode = helpmode;
  1532.    helpmode = HELP3DMODE;
  1533.  
  1534.    k = fullscreen_prompt("3D Mode Selection",k+1,prompts3d,uvalues,0,0,NULL);
  1535.    helpmode = oldhelpmode;
  1536.    if (k < 0) {
  1537.       EXIT_OVLY;
  1538.       return(-1);
  1539.       }
  1540.  
  1541.    k=0;
  1542.  
  1543.    preview = uvalues[k++].uval.ch.val;
  1544.  
  1545.    showbox = uvalues[k++].uval.ch.val;
  1546.  
  1547.    previewfactor  = uvalues[k++].uval.ival;
  1548.  
  1549.    sphere = uvalues[k++].uval.ch.val;
  1550.  
  1551.    glassestype = uvalues[k++].uval.ival;
  1552.  
  1553.    RAY = uvalues[k++].uval.ival;
  1554.    k++;
  1555.  
  1556.    BRIEF = uvalues[k++].uval.ch.val;
  1557.  
  1558.    strcpy(ray_name,uvalues[k++].uval.sval);
  1559.  
  1560.    Targa_Out = uvalues[k++].uval.ch.val;
  1561.  
  1562.    /* check ranges */
  1563.    if(previewfactor < 2)
  1564.       previewfactor = 2;
  1565.    if(previewfactor > 2000)
  1566.       previewfactor = 2000;
  1567.  
  1568.    if(sphere && !SPHERE)
  1569.    {
  1570.       SPHERE = TRUE;
  1571.       set_3d_defaults();
  1572.    }
  1573.    else if(!sphere && SPHERE)
  1574.    {
  1575.       SPHERE = FALSE;
  1576.       set_3d_defaults();
  1577.    }
  1578.  
  1579.    if(glassestype < 0)
  1580.       glassestype = 0;
  1581.    if(glassestype > 3)
  1582.       glassestype = 3;
  1583.    if(glassestype)
  1584.       whichimage = 1;
  1585.  
  1586.    if (RAY < 0)
  1587.       RAY = 0;
  1588.    if (RAY > 7)
  1589.       RAY = 7;
  1590.  
  1591.    if (!RAY)
  1592.    {
  1593.       k = 0;
  1594.       choices[k++] = "make a surface grid";
  1595.       choices[k++] = "just draw the points";
  1596.       choices[k++] = "connect the dots (wire frame)";
  1597.       choices[k++] = "surface fill (colors interpolated)";
  1598.       choices[k++] = "surface fill (colors not interpolated)";
  1599.       choices[k++] = "solid fill (bars up from \"ground\")";
  1600.       if(SPHERE)
  1601.       {
  1602.          choices[k++] = "light source";
  1603.       }
  1604.       else
  1605.       {
  1606.          choices[k++] = "light source before transformation";
  1607.          choices[k++] = "light source after transformation";
  1608.       }
  1609.       for (i = 0; i < k; ++i)
  1610.      attributes[i] = 1;
  1611.       helpmode = HELP3DFILL;
  1612.       i = fullscreen_choice(CHOICEHELP,"Select 3D Fill Type",NULL,NULL,
  1613.                   k,choices,attributes,
  1614.                   0,0,0,FILLTYPE+1,NULL,NULL,NULL,NULL);
  1615.       helpmode = oldhelpmode;
  1616.       if (i < 0)
  1617.      goto restart_1;
  1618.       FILLTYPE = i-1;
  1619.  
  1620.       if(glassestype)
  1621.       {
  1622.      if(get_funny_glasses_params())
  1623.             goto restart_1;
  1624.          }
  1625.          if (check_mapfile())
  1626.              goto restart_1;
  1627.       }
  1628.    restart_3:
  1629.  
  1630.    if(SPHERE)
  1631.    {
  1632.       k = -1;
  1633.       LOADPROMPTS3D("Longitude start (degrees)");
  1634.       LOADPROMPTS3D("Longitude stop  (degrees)");
  1635.       LOADPROMPTS3D("Latitude start  (degrees)");
  1636.       LOADPROMPTS3D("Latitude stop   (degrees)");
  1637.       LOADPROMPTS3D("Radius scaling factor in pct");
  1638.    }
  1639.    else
  1640.    {
  1641.       k = -1;
  1642.       if (!RAY)
  1643.       {
  1644.          LOADPROMPTS3D("X-axis rotation in degrees");
  1645.          LOADPROMPTS3D("Y-axis rotation in degrees");
  1646.          LOADPROMPTS3D("Z-axis rotation in degrees");
  1647.       }
  1648.       LOADPROMPTS3D("X-axis scaling factor in pct");
  1649.       LOADPROMPTS3D("Y-axis scaling factor in pct");
  1650.    }
  1651.    k = -1;
  1652.    if (!(RAY && !SPHERE))
  1653.    {
  1654.       uvalues[++k].uval.ival   = XROT     ;
  1655.       uvalues[k].type = 'i';
  1656.       uvalues[++k].uval.ival   = YROT     ;
  1657.       uvalues[k].type = 'i';
  1658.       uvalues[++k].uval.ival   = ZROT     ;
  1659.       uvalues[k].type = 'i';
  1660.    }
  1661.    uvalues[++k].uval.ival   = XSCALE    ;
  1662.    uvalues[k].type = 'i';
  1663.  
  1664.    uvalues[++k].uval.ival   = YSCALE    ;
  1665.    uvalues[k].type = 'i';
  1666.  
  1667.    LOADPROMPTS3D("Surface Roughness scaling factor in pct");
  1668.    uvalues[k].type = 'i';
  1669.    uvalues[k].uval.ival = ROUGH     ;
  1670.  
  1671.    LOADPROMPTS3D("'Water Level' (minimum color value)");
  1672.    uvalues[k].type = 'i';
  1673.    uvalues[k].uval.ival = WATERLINE ;
  1674.  
  1675.    if(!RAY)
  1676.    {
  1677.       LOADPROMPTS3D("Perspective distance [1 - 999, 0 for no persp])");
  1678.       uvalues[k].type = 'i';
  1679.       uvalues[k].uval.ival = ZVIEWER     ;
  1680.  
  1681.       LOADPROMPTS3D("X shift with perspective (positive = right)");
  1682.       uvalues[k].type = 'i';
  1683.       uvalues[k].uval.ival = XSHIFT    ;
  1684.    
  1685.       LOADPROMPTS3D("Y shift with perspective (positive = up   )");
  1686.       uvalues[k].type = 'i';
  1687.       uvalues[k].uval.ival = YSHIFT    ;
  1688.    
  1689.       LOADPROMPTS3D("Image non-perspective X adjust (positive = right)");
  1690.       uvalues[k].type = 'i';
  1691.       uvalues[k].uval.ival = xtrans    ;
  1692.    
  1693.       LOADPROMPTS3D("Image non-perspective Y adjust (positive = up)");
  1694.       uvalues[k].type = 'i';
  1695.       uvalues[k].uval.ival = ytrans    ;
  1696.    
  1697.       LOADPROMPTS3D("First transparent color");
  1698.       uvalues[k].type = 'i';
  1699.       uvalues[k].uval.ival = transparent[0];
  1700.    
  1701.       LOADPROMPTS3D("Last transparent color");
  1702.       uvalues[k].type = 'i';
  1703.       uvalues[k].uval.ival = transparent[1];
  1704.    }
  1705.  
  1706.    LOADPROMPTS3D("Randomize Colors      (0 - 7, '0' disables)");
  1707.    uvalues[k].type = 'i';
  1708.    uvalues[k++].uval.ival = RANDOMIZE;
  1709.  
  1710.    if (SPHERE)
  1711.       s = "              Sphere 3D Parameters\n\
  1712. Sphere is on its side; North pole to right\n\
  1713. Long. 180 is top, 0 is bottom; Lat. -90 is left, 90 is right";
  1714.    else
  1715.       s = "              Planar 3D Parameters\n\
  1716. Pre-rotation X axis is screen top; Y axis is left side\n\
  1717. Pre-rotation Z axis is coming at you out of the screen!";
  1718.  
  1719.    helpmode = HELP3DPARMS;
  1720.    k = fullscreen_prompt(s,k,prompts3d,uvalues,0,0,NULL);
  1721.    helpmode = oldhelpmode;
  1722.    if (k < 0)
  1723.       goto restart_1;
  1724.  
  1725.    k = 0;
  1726.    if (!(RAY && !SPHERE))
  1727.    {
  1728.       XROT    = uvalues[k++].uval.ival;
  1729.       YROT    = uvalues[k++].uval.ival;
  1730.       ZROT    = uvalues[k++].uval.ival;
  1731.    }
  1732.    XSCALE     = uvalues[k++].uval.ival;
  1733.    YSCALE     = uvalues[k++].uval.ival;
  1734.    ROUGH      = uvalues[k++].uval.ival;
  1735.    WATERLINE  = uvalues[k++].uval.ival;
  1736.    if (!RAY)
  1737.    {
  1738.       ZVIEWER = uvalues[k++].uval.ival;
  1739.    XSHIFT     = uvalues[k++].uval.ival;
  1740.    YSHIFT     = uvalues[k++].uval.ival;
  1741.    xtrans     = uvalues[k++].uval.ival;
  1742.    ytrans     = uvalues[k++].uval.ival;
  1743.    transparent[0] = uvalues[k++].uval.ival;
  1744.    transparent[1] = uvalues[k++].uval.ival;
  1745.    }
  1746.    RANDOMIZE  = uvalues[k++].uval.ival;
  1747.    if (RANDOMIZE >= 7) RANDOMIZE = 7;
  1748.    if (RANDOMIZE <= 0) RANDOMIZE = 0;
  1749.  
  1750.    if ((Targa_Out || ILLUMINE || RAY))
  1751.     if(get_light_params())
  1752.         goto restart_3;
  1753.  
  1754. EXIT_OVLY;
  1755. return(0);
  1756. }
  1757.  
  1758. /* --------------------------------------------------------------------- */
  1759. static int get_light_params()
  1760. {
  1761.    char far *prompts3d[13];
  1762.    struct fullscreenvalues uvalues[13];
  1763.  
  1764.    int k;
  1765.    int oldhelpmode;
  1766.  
  1767.    /* defaults go here */
  1768.  
  1769.    k = -1;
  1770.  
  1771.    if (ILLUMINE || RAY)
  1772.    {
  1773.    LOADPROMPTS3D("X value light vector");
  1774.    uvalues[k].type = 'i';
  1775.    uvalues[k].uval.ival = XLIGHT    ;
  1776.  
  1777.    LOADPROMPTS3D("Y value light vector");
  1778.    uvalues[k].type = 'i';
  1779.    uvalues[k].uval.ival = YLIGHT    ;
  1780.  
  1781.    LOADPROMPTS3D("Z value light vector");
  1782.    uvalues[k].type = 'i';
  1783.    uvalues[k].uval.ival = ZLIGHT    ;
  1784.  
  1785.         if (!RAY)
  1786.         {
  1787.    LOADPROMPTS3D("Light Source Smoothing Factor");
  1788.    uvalues[k].type = 'i';
  1789.    uvalues[k].uval.ival = LIGHTAVG  ;
  1790.  
  1791.    LOADPROMPTS3D("Ambient");
  1792.    uvalues[k].type = 'i';
  1793.    uvalues[k].uval.ival = Ambient;
  1794.         }
  1795.    }
  1796.  
  1797.    if (Targa_Out && !RAY)
  1798.    {
  1799.     LOADPROMPTS3D("Haze Factor        (0 - 100, '0' disables)");
  1800.     uvalues[k].type = 'i';
  1801.     uvalues[k].uval.ival= haze;
  1802.  
  1803.         if (!Targa_Overlay)
  1804.     check_writefile(light_name,".tga");
  1805.       LOADPROMPTS3D("Targa File Name  (Assume .tga)");
  1806.     uvalues[k].type = 's';
  1807.     strcpy(uvalues[k].uval.sval,light_name);
  1808.  
  1809.       LOADPROMPTS3D("Back Ground Color (0 - 255)");
  1810.       uvalues[k].type = '*';
  1811.  
  1812.       LOADPROMPTS3D("   Red");
  1813.       uvalues[k].type = 'i';
  1814.       uvalues[k].uval.ival = (int)back_color[0];
  1815.  
  1816.       LOADPROMPTS3D("   Green");
  1817.       uvalues[k].type = 'i';
  1818.       uvalues[k].uval.ival = (int)back_color[1];
  1819.  
  1820.       LOADPROMPTS3D("   Blue");
  1821.       uvalues[k].type = 'i';
  1822.       uvalues[k].uval.ival = (int)back_color[2];
  1823.  
  1824.       LOADPROMPTS3D("Overlay Targa File? (Y/N)");
  1825.       uvalues[k].type = 'y';
  1826.       uvalues[k].uval.ch.val = Targa_Overlay;
  1827.  
  1828.    }
  1829.  
  1830.    LOADPROMPTS3D("");
  1831.  
  1832.    oldhelpmode = helpmode;
  1833.    helpmode = HELP3DLIGHT;
  1834.    k = fullscreen_prompt("Light Source Parameters",k,prompts3d,uvalues,0,0,NULL);
  1835.    helpmode = oldhelpmode;
  1836.    if (k < 0)
  1837.       return(-1);
  1838.  
  1839.    k = 0;
  1840.    if (ILLUMINE)
  1841.    {
  1842.       XLIGHT   = uvalues[k++].uval.ival;
  1843.       YLIGHT   = uvalues[k++].uval.ival;
  1844.       ZLIGHT   = uvalues[k++].uval.ival;
  1845.       if (!RAY)
  1846.         {
  1847.       LIGHTAVG = uvalues[k++].uval.ival;
  1848.       Ambient  = uvalues[k++].uval.ival;
  1849.       if (Ambient >= 100) Ambient = 100;
  1850.       if (Ambient <= 0) Ambient = 0;
  1851.         }
  1852.    }
  1853.  
  1854.    if (Targa_Out && !RAY)
  1855.    {
  1856.     haze  =  uvalues[k++].uval.ival;
  1857.     if (haze >= 100) haze = 100;
  1858.     if (haze <= 0) haze = 0;
  1859.         strcpy(light_name,uvalues[k++].uval.sval);
  1860.         /* In case light_name conflicts with an existing name it is checked
  1861.             again in line3d */
  1862.         k++;
  1863.         back_color[0] = (char)uvalues[k++].uval.ival % 255;
  1864.         back_color[1] = (char)uvalues[k++].uval.ival % 255;
  1865.         back_color[2] = (char)uvalues[k++].uval.ival % 255;
  1866.         Targa_Overlay = uvalues[k].uval.ch.val;
  1867.    }
  1868.    return(0);
  1869. }
  1870.  
  1871. /* --------------------------------------------------------------------- */
  1872.  
  1873.  
  1874. static int check_mapfile()
  1875. {
  1876.    extern BYTE dacbox[256][3];
  1877.    extern BYTE olddacbox[256][3];
  1878.    int askflag = 0;
  1879.    int i,oldhelpmode;
  1880.    strcpy(temp1,"*");
  1881.    if (mapset)
  1882.       strcpy(temp1,MAP_name);
  1883.    if (!(glassestype == 1 || glassestype == 2))
  1884.       askflag = 1;
  1885.    else
  1886.       strcpy(temp1,funnyglasses_map_name);
  1887.    while (TRUE) {
  1888.       if (askflag) {
  1889.      oldhelpmode = helpmode;
  1890.      helpmode = -1;
  1891.      i = field_prompt(0,"\
  1892. Enter name of .MAP file to use,\n\
  1893. or '*' to use palette from the image to be loaded.",
  1894.          NULL,temp1,60,NULL);
  1895.      helpmode = oldhelpmode;
  1896.      if (i < 0)
  1897.         return(-1);
  1898.         if (temp1[0] == '*') {
  1899.             mapset = 0;
  1900.             break;
  1901.             }
  1902.         }
  1903.         memcpy(olddacbox,dacbox,256*3); /* save the DAC */
  1904.       i = ValidateLuts(temp1);
  1905.       memcpy(dacbox,olddacbox,256*3); /* restore the DAC */
  1906.       if (i != 0) { /* Oops, somethings wrong */
  1907.          askflag = 1;
  1908.      continue;
  1909.      }
  1910.       mapset = 1;
  1911.       strcpy (MAP_name,temp1);
  1912.       break;
  1913.       }
  1914.    return(0);
  1915. }
  1916.  
  1917. static int get_funny_glasses_params()
  1918. {
  1919.    char far *prompts3d[10];
  1920.  
  1921.    struct fullscreenvalues uvalues[10];
  1922.  
  1923.    int k;
  1924.    int oldhelpmode;
  1925.  
  1926.    /* defaults */
  1927.    if(ZVIEWER == 0)
  1928.       ZVIEWER = 150;
  1929.    if(eyeseparation == 0)
  1930.    {
  1931.       if(fractype==IFS3D || fractype==LLORENZ3D || fractype==FPLORENZ3D)
  1932.       {
  1933.      eyeseparation =  2;
  1934.      xadjust       = -2;
  1935.       }
  1936.       else
  1937.       {
  1938.      eyeseparation =  3;
  1939.      xadjust       =  0;
  1940.       }
  1941.    }
  1942.  
  1943.    if(glassestype == 1)
  1944.       strcpy(funnyglasses_map_name,"glasses1.map");
  1945.    else if(glassestype == 2)
  1946.    {
  1947.       if(FILLTYPE == -1)
  1948.      strcpy(funnyglasses_map_name,"grid.map");
  1949.       else
  1950.      strcpy(funnyglasses_map_name,"glasses2.map");
  1951.    }
  1952.  
  1953.    k = -1;
  1954.    LOADPROMPTS3D("Interocular distance (as % of screen)");
  1955.    uvalues[k].type = 'i';
  1956.    uvalues[k].uval.ival= eyeseparation;
  1957.  
  1958.    LOADPROMPTS3D("Convergence adjust (positive = spread greater)");
  1959.    uvalues[k].type = 'i';
  1960.    uvalues[k].uval.ival = xadjust;
  1961.  
  1962.    LOADPROMPTS3D("Left  red image crop (% of screen)");
  1963.    uvalues[k].type = 'i';
  1964.    uvalues[k].uval.ival = red_crop_left;
  1965.  
  1966.    LOADPROMPTS3D("Right red image crop (% of screen)");
  1967.    uvalues[k].type = 'i';
  1968.    uvalues[k].uval.ival = red_crop_right;
  1969.  
  1970.    LOADPROMPTS3D("Left  blue image crop (% of screen)");
  1971.    uvalues[k].type = 'i';
  1972.    uvalues[k].uval.ival = blue_crop_left;
  1973.  
  1974.    LOADPROMPTS3D("Right blue image crop (% of screen)");
  1975.    uvalues[k].type = 'i';
  1976.    uvalues[k].uval.ival = blue_crop_right;
  1977.  
  1978.    LOADPROMPTS3D("Red brightness factor (%)");
  1979.    uvalues[k].type = 'i';
  1980.    uvalues[k].uval.ival = red_bright;
  1981.  
  1982.    LOADPROMPTS3D("Blue brightness factor (%)");
  1983.    uvalues[k].type = 'i';
  1984.    uvalues[k].uval.ival = blue_bright;
  1985.  
  1986.    if(glassestype == 1 || glassestype == 2)
  1987.    {
  1988.       LOADPROMPTS3D("Map File name");
  1989.       uvalues[k].type = 's';
  1990.       strcpy(uvalues[k].uval.sval,funnyglasses_map_name);
  1991.    }
  1992.  
  1993.    oldhelpmode = helpmode;
  1994.    helpmode = HELP3DGLASSES;
  1995.    k = fullscreen_prompt("Funny Glasses Parameters",k+1,prompts3d,uvalues,0,0,NULL);
  1996.    helpmode = oldhelpmode;
  1997.    if (k < 0)
  1998.       return(-1);
  1999.  
  2000.    k = 0;
  2001.    eyeseparation   =  uvalues[k++].uval.ival;
  2002.    xadjust       =  uvalues[k++].uval.ival;
  2003.    red_crop_left   =  uvalues[k++].uval.ival;
  2004.    red_crop_right  =  uvalues[k++].uval.ival;
  2005.    blue_crop_left  =  uvalues[k++].uval.ival;
  2006.    blue_crop_right =  uvalues[k++].uval.ival;
  2007.    red_bright       =  uvalues[k++].uval.ival;
  2008.    blue_bright       =  uvalues[k++].uval.ival;
  2009.  
  2010.    if(glassestype == 1 || glassestype == 2)
  2011.       strcpy(funnyglasses_map_name,uvalues[k].uval.sval);
  2012.    return(0);
  2013. }
  2014.  
  2015. /* --------------------------------------------------------------------- */
  2016.  
  2017. static int edit_ifs_params()    /* prompt for IFS params */
  2018. {
  2019.    int totcols;
  2020.    int i, j, k, numlines, ret;
  2021.    FILE *tempfile;
  2022.    char msg[81];
  2023.    char filename[81];
  2024.    float ftemp;
  2025.    int oldhelpmode;
  2026.    int low, hi;
  2027.  
  2028.    if (!ifs_defn && !ifsload())
  2029.       return(-1);
  2030.  
  2031.    totcols = (ifs_type == 0) ? IFSPARM : IFS3DPARM;
  2032.    ret = 0;
  2033.    oldhelpmode = helpmode;
  2034.    helpmode = HT_IFS;
  2035.  
  2036.    low = 0;
  2037.  
  2038.    for ( ;; ) {
  2039. static char far ifshdg2[]={"2D IFS Parameters"};
  2040. static char far ifshdg3[]={"3D IFS Parameters"};
  2041. static char far ifsparmmsg1[]={"#    a     b     c     d     e     f"};
  2042. static char far ifsparmmsg2[]={"     g     h     i     j     k     l"};
  2043. static char far ifsprompt[]={"\
  2044. Enter the number of the line you want to edit,\n\
  2045. S to save, F6 for corners, or ENTER to end ==>"};
  2046.       int leftcol,promptrow,promptcol;
  2047. #define IFS_NUM 12
  2048.  
  2049.       for (numlines = 0; numlines < NUMIFS; numlines++) /* find the first zero entry */
  2050.      if (ifs_defn[(numlines * totcols) + totcols - 1] <= 0.0001) break;
  2051.  
  2052.       helptitle();
  2053.       setattr(1,0,C_PROMPT_BKGRD,24*80); /* init rest of screen to background */
  2054.       putstringcenter(2,0,80,C_GENERAL_HI,(ifs_type == 0) ? ifshdg2 : ifshdg3);
  2055.       leftcol = (ifs_type == 0) ? 15 : 0;
  2056.       putstring(4,leftcol+1,C_GENERAL_HI,ifsparmmsg1);
  2057.       if (ifs_type != 0)
  2058.      putstring(-1,-1,C_GENERAL_HI,ifsparmmsg2);
  2059.       putstring(-1,-1,C_GENERAL_HI,"   prob \n\n");
  2060.  
  2061.       hi = low+IFS_NUM;
  2062.       if (hi>numlines) hi = numlines;
  2063.       for (i = low; i < hi; i++) {
  2064.      sprintf(msg,"%2d", i+1);
  2065.      putstring(5+i-low,leftcol,C_GENERAL_HI,msg);
  2066.      for (j = 0; j < totcols; j++) {
  2067.         sprintf(msg,"%6.2f",ifs_defn[(i*totcols)+j]);
  2068.         putstring(-1,-1,C_GENERAL_MED,msg);
  2069.         }
  2070.      }
  2071.       if (hi<numlines) {
  2072.      putstring(5+IFS_NUM,leftcol,C_GENERAL_HI,"(more)");
  2073.       }
  2074.  
  2075.       textcbase = 14;
  2076.       putstring(5+i-low+1,0,C_GENERAL_HI,ifsprompt);
  2077.       promptrow = textrow;
  2078.       promptcol = textcol + textcbase + 1;
  2079.       temp1[0] = textcbase = 0;
  2080.       promptfkeys = 1<<6;
  2081.       i = input_field(0,C_GENERAL_INPUT,temp1,2,promptrow,promptcol,
  2082.           prompt_checkkey);
  2083.       if (i<0) {
  2084.       break;
  2085.       } else if (i==PAGE_UP) {
  2086.       low -= IFS_NUM;
  2087.       if (low<0) low=0;
  2088.       } else if (i==UP_ARROW) {
  2089.       low -= 1;
  2090.       if (low<0) low=0;
  2091.       } else if (i==DOWN_ARROW) {
  2092.       low += 1;
  2093.       if (low+IFS_NUM>numlines) low=numlines-IFS_NUM;
  2094.       if (low<0) low=0;
  2095.       } else if (i==PAGE_DOWN) {
  2096.       low += IFS_NUM;
  2097.       if (low+IFS_NUM>numlines) low=numlines-IFS_NUM;
  2098.       if (low<0) low=0;
  2099.       } else if (i==F6) {
  2100.       if (get_corners()) {
  2101.           ret = 1;
  2102.       }
  2103.       } else if (i==0) {
  2104.       if (temp1[0]==0) break;
  2105.       } else {
  2106.       continue;
  2107.       }
  2108.  
  2109.       putstring(promptrow,promptcol,C_GENERAL_HI,temp1);
  2110.       if (temp1[0] == 's' || temp1[0] == 'S') {
  2111.      stackscreen();
  2112.      filename[0] = 0;
  2113.      i = field_prompt(0,"Enter the name of the .IFS file to save:",
  2114.              NULL,filename,60,NULL);
  2115.      unstackscreen();
  2116.      if (i != -1) {
  2117.         if (strchr(filename,'.') == NULL)
  2118.            strcat(filename,".ifs");
  2119.         if ((tempfile=fopen(filename,"w")) != NULL) {
  2120.            for (i = 0; i < numlines; i++) {
  2121.           for (j = 0; j < totcols; j++)
  2122.              fprintf(tempfile, "%6.2f", (float)ifs_defn[(i*totcols)+j]);
  2123.           fprintf(tempfile, "\n");
  2124.           }
  2125.            fclose(tempfile);
  2126.            ifs_changed = 0;
  2127.            }
  2128.         else {
  2129.            static char far msg[]={"Could not create file"};
  2130.            stopmsg(0,msg);
  2131.            }
  2132.         }
  2133.      continue;
  2134.      }
  2135.       i = atoi(temp1) - 1;
  2136.       if (i >= 0 && i < numlines) {
  2137.      for (j = 0; j < totcols; j++) {
  2138.         if (j < totcols-1)
  2139.            sprintf(msg,"Parameter %c",'a'+j);
  2140.         else
  2141.            sprintf(msg,"Probability");
  2142.         putstring(promptrow+2,25,C_GENERAL_HI,msg);
  2143.         sprintf(temp1,"%6.2f",(float)ifs_defn[k=(i*totcols)+j]);
  2144.         if (input_field(1,C_GENERAL_INPUT,temp1,6,
  2145.                 textrow,textcol+1,NULL) < 0)
  2146.            break;
  2147.         if (ifs_defn[k] != (ftemp = atof(temp1))) {
  2148.            ifs_defn[k] = ftemp;
  2149.            ret = ifs_changed = 1;
  2150.            }
  2151.         }
  2152.      memset(msg,' ',80); msg[81] = 0;
  2153.      putstring(promptrow+2,0,C_PROMPT_BKGRD,msg);
  2154.      }
  2155.       }
  2156.  
  2157.    helpmode = oldhelpmode;
  2158.    return(ret);
  2159. }
  2160.  
  2161. /* --------------------------------------------------------------------- */
  2162. /*
  2163.     get_toggles() is called from FRACTINT.C whenever the 'x' key
  2164.     is pressed.  This routine prompts for several options,
  2165.     sets the appropriate variables, and returns the following code
  2166.     to the calling routine:
  2167.  
  2168.     -1  routine was ESCAPEd - no need to re-generate the image.
  2169.      0  nothing changed, or minor variable such as "overwrite=".
  2170.         No need to re-generate the image.
  2171.      1  major variable changed (such as "inside=").  Re-generate
  2172.         the image.
  2173.  
  2174.     Finally, remember to insert variables in the list *and* check
  2175.     for them in the same order!!!
  2176. */
  2177. #define LOADCHOICES(X)     {\
  2178.    static char far tmp[] = { X };\
  2179.    choices[++k]= tmp;\
  2180.    }
  2181. int get_toggles()
  2182. {
  2183.    char far *choices[20];
  2184.    int oldhelpmode;
  2185.    char prevsavename[81];
  2186.    struct fullscreenvalues uvalues[25];
  2187.    int i, j, k;
  2188.    char old_usr_stdcalcmode;
  2189.    int old_maxit,old_inside,old_outside,old_soundflag;
  2190.    int old_logflag,old_biomorph,old_decomp;
  2191.    int old_fillcolor;
  2192.    static char *calcmodes[] ={"1","2","g","b","t"};
  2193.    static char *soundmodes[5]={"yes","no","x","y","z"};
  2194.  
  2195.    ENTER_OVLY(OVLY_PROMPTS);
  2196.  
  2197.    k = -1;
  2198.  
  2199.    LOADCHOICES("Passes (1, 2, g[uessing], b[oundary trace], t[esseral])");
  2200.    uvalues[k].type = 'l';
  2201.    uvalues[k].uval.ch.vlen = 3;
  2202.    uvalues[k].uval.ch.llen = sizeof(calcmodes)/sizeof(*calcmodes);
  2203.    uvalues[k].uval.ch.list = calcmodes;
  2204.    uvalues[k].uval.ch.val = (usr_stdcalcmode == '1') ? 0
  2205.               : (usr_stdcalcmode == '2') ? 1
  2206.                           : (usr_stdcalcmode == 'g') ? 2
  2207.                           : (usr_stdcalcmode == 'b') ? 3 :4 ;
  2208.    old_usr_stdcalcmode = usr_stdcalcmode;
  2209.  
  2210.    LOADCHOICES("Floating Point Algorithm");
  2211.    uvalues[k].type = 'y';
  2212.    uvalues[k].uval.ch.val = usr_floatflag;
  2213.  
  2214.    LOADCHOICES("Maximum Iterations (2 to 32767)");
  2215.    uvalues[k].type = 'i';
  2216.    uvalues[k].uval.ival = old_maxit = maxit;
  2217.  
  2218.    LOADCHOICES("Inside Color (<nnn>,maxiter,zmag,bof60,bof61,epscr,star,per)");
  2219.    uvalues[k].type = 's';
  2220.    if(inside == -59)
  2221.       strcpy(uvalues[k].uval.sval,s_zmag);
  2222.    else if(inside == -60)
  2223.       strcpy(uvalues[k].uval.sval,s_bof60);
  2224.    else if(inside == -61)
  2225.       strcpy(uvalues[k].uval.sval,s_bof61);
  2226.    else if(inside == -100)
  2227.       strcpy(uvalues[k].uval.sval,s_epscross);
  2228.    else if(inside == -101)
  2229.       strcpy(uvalues[k].uval.sval,s_startrail);
  2230.    else if(inside == -102)
  2231.       strcpy(uvalues[k].uval.sval,s_period);
  2232.    else if(inside == -1)
  2233.       strcpy(uvalues[k].uval.sval,s_maxiter);
  2234.    else
  2235.       sprintf(uvalues[k].uval.sval,"%d",inside);
  2236.    old_inside = inside;
  2237.  
  2238.    LOADCHOICES("Outside Color (<nnn>,iter,real,imag,mult,summ)");
  2239.    uvalues[k].type = 's';
  2240.    if(outside == -1)
  2241.       strcpy(uvalues[k].uval.sval,s_iter);
  2242.    else if(outside == -2)
  2243.       strcpy(uvalues[k].uval.sval,s_real);
  2244.    else if(outside == -3)
  2245.       strcpy(uvalues[k].uval.sval,s_imag);
  2246.    else if(outside == -4)
  2247.       strcpy(uvalues[k].uval.sval,s_mult);
  2248.    else if(outside == -5)
  2249.       strcpy(uvalues[k].uval.sval,s_sum);
  2250.    else
  2251.       sprintf(uvalues[k].uval.sval,"%d",outside);
  2252.    old_outside = outside;
  2253.  
  2254.    LOADCHOICES("Savename (.GIF implied)");
  2255.    uvalues[k].type = 's';
  2256.    strcpy(prevsavename,savename);
  2257.    strcpy(uvalues[k].uval.sval,savename);
  2258.  
  2259.    LOADCHOICES("File Overwrite ('overwrite=')");
  2260.    uvalues[k].type = 'y';
  2261.    uvalues[k].uval.ch.val = overwrite;
  2262.  
  2263.    LOADCHOICES("Sound (no, yes, x, y, z)");
  2264.    uvalues[k].type = 'l';
  2265.    uvalues[k].uval.ch.vlen = 3;
  2266.    uvalues[k].uval.ch.llen = 5;
  2267.    uvalues[k].uval.ch.list = soundmodes;
  2268.    uvalues[k].uval.ch.val = 1 + (old_soundflag = soundflag);
  2269.  
  2270.    if (rangeslen == 0) {
  2271.       LOADCHOICES("Log Palette (0=no,1=yes,-1=old,+n=cmprsd,-n=sqrt)");
  2272.       uvalues[k].type = 'i';
  2273.       }
  2274.    else {
  2275.       LOADCHOICES("Log Palette (n/a, ranges= parameter is in effect)");
  2276.       uvalues[k].type = '*';
  2277.       }
  2278.    uvalues[k].uval.ival = old_logflag = LogFlag;
  2279.  
  2280.    LOADCHOICES("Biomorph Color (-1 means OFF)");
  2281.    uvalues[k].type = 'i';
  2282.    uvalues[k].uval.ival = old_biomorph = usr_biomorph;
  2283.  
  2284.    LOADCHOICES("Decomp Option (2,4,8,..,256, 0=OFF)");
  2285.    uvalues[k].type = 'i';
  2286.    uvalues[k].uval.ival = old_decomp = decomp[0];
  2287.  
  2288.    LOADCHOICES("Fill Color (normal,<nnn>) (works with passes=t and =b)");
  2289.    uvalues[k].type = 's';
  2290.    if(fillcolor < 0)
  2291.       strcpy(uvalues[k].uval.sval,s_normal);
  2292.    else
  2293.       sprintf(uvalues[k].uval.sval,"%d",fillcolor);
  2294.    old_fillcolor = fillcolor;
  2295.  
  2296.    LOADCHOICES("Orbit delay (0 = none)");
  2297.    uvalues[k].type = 'i';
  2298.    uvalues[k].uval.ival = orbit_delay;
  2299.  
  2300. /*
  2301.    LOADCHOICES("Antialiasing (0 to 8)");
  2302.    uvalues[k].type = 'i';
  2303.    uvalues[k].uval.ival = AntiAliasing;
  2304. */
  2305.  
  2306.    oldhelpmode = helpmode;
  2307.    helpmode = HELPXOPTS;
  2308.    i = fullscreen_prompt("        Basic Options\n\
  2309. (not all combinations make sense)",
  2310.      k+1,choices,uvalues,0,0,NULL);
  2311.    helpmode = oldhelpmode;
  2312.    if (i < 0) {
  2313.       EXIT_OVLY;
  2314.       return(-1);
  2315.       }
  2316.  
  2317.    /* now check out the results (*hopefully* in the same order <grin>) */
  2318.    k = -1;
  2319.    j = 0;   /* return code */
  2320.  
  2321.    usr_stdcalcmode = calcmodes[uvalues[++k].uval.ch.val][0];
  2322.    if (old_usr_stdcalcmode != usr_stdcalcmode) j = 1;
  2323.  
  2324.    if (uvalues[++k].uval.ch.val != usr_floatflag) {
  2325.       usr_floatflag = uvalues[k].uval.ch.val;
  2326.       j = 1;
  2327.       }
  2328.  
  2329.    ++k;
  2330.    maxit = uvalues[k].uval.ival;
  2331.    if (maxit < 2) maxit = 2;
  2332.  
  2333. /* 'maxit' is an int so it is always <= 32767, MCP 12-3-91
  2334.    if (maxit > 32767) maxit = 32767;
  2335. */
  2336.  
  2337.    if (maxit != old_maxit) j = 1;
  2338.  
  2339.    if(strncmp(strlwr(uvalues[++k].uval.sval),s_zmag,4)==0)
  2340.       inside = -59;
  2341.    else if(strncmp(strlwr(uvalues[k].uval.sval),s_bof60,5)==0)
  2342.       inside = -60;
  2343.    else if(strncmp(strlwr(uvalues[k].uval.sval),s_bof61,5)==0)
  2344.       inside = -61;
  2345.    else if(strncmp(strlwr(uvalues[k].uval.sval),s_epscross,3)==0)
  2346.       inside = -100;
  2347.    else if(strncmp(strlwr(uvalues[k].uval.sval),s_startrail,4)==0)
  2348.       inside = -101;
  2349.    else if(strncmp(strlwr(uvalues[k].uval.sval),s_period,3)==0)
  2350.       inside = -102;
  2351.    else if(strncmp(strlwr(uvalues[k].uval.sval),s_maxiter,5)==0)
  2352.       inside = -1;
  2353.    else
  2354.       inside = atoi(uvalues[k].uval.sval);
  2355.    if (inside != old_inside) j = 1;
  2356.  
  2357.    if(strncmp(strlwr(uvalues[++k].uval.sval),s_real,4)==0)
  2358.       outside = -2;
  2359.    else if(strncmp(strlwr(uvalues[k].uval.sval),s_imag,4)==0)
  2360.       outside = -3;
  2361.    else if(strncmp(strlwr(uvalues[k].uval.sval),s_mult,4)==0)
  2362.       outside = -4;
  2363.    else if(strncmp(strlwr(uvalues[k].uval.sval),s_sum,4)==0)
  2364.       outside = -5;
  2365.    else if(strncmp(strlwr(uvalues[k].uval.sval),s_iter,4)==0)
  2366.       outside = -1;
  2367.    else
  2368.       outside = atoi(uvalues[k].uval.sval);
  2369.    if (outside != old_outside) j = 1;
  2370.  
  2371.    strcpy(savename,uvalues[++k].uval.sval);
  2372.    if (strcmp(savename,prevsavename))
  2373.       resave_flag = started_resaves = 0; /* forget pending increment */
  2374.  
  2375.    overwrite = uvalues[++k].uval.ch.val;
  2376.  
  2377.    soundflag = uvalues[++k].uval.ch.val - 1;
  2378.    if (soundflag != old_soundflag && (soundflag > 1 || old_soundflag > 1))
  2379.       j = 1;
  2380.  
  2381.    LogFlag = uvalues[++k].uval.ival;
  2382.    if (LogFlag != old_logflag) j = 1;
  2383.  
  2384.    usr_biomorph = uvalues[++k].uval.ival;
  2385.    if (usr_biomorph != old_biomorph) j = 1;
  2386.  
  2387.    decomp[0] = uvalues[++k].uval.ival;
  2388.    if (decomp[0] != old_decomp) j = 1;
  2389.  
  2390.    if(strncmp(strlwr(uvalues[++k].uval.sval),s_normal,4)==0)
  2391.       fillcolor = -1;
  2392.    else
  2393.       fillcolor = atoi(uvalues[k].uval.sval);
  2394.    if (fillcolor != old_fillcolor) j = 1;
  2395.  
  2396.    orbit_delay = uvalues[++k].uval.ival;
  2397.  
  2398. /*
  2399.    if(AntiAliasing != uvalues[++k].uval.ival) j = 1;
  2400.    AntiAliasing = uvalues[k].uval.ival;
  2401.    if(AntiAliasing < 0) AntiAliasing = 0;
  2402.    if(AntiAliasing > 8) AntiAliasing = 8;
  2403. */
  2404.  
  2405.    EXIT_OVLY;
  2406.    return(j);
  2407. }
  2408.  
  2409. /*
  2410.     get_toggles2() is similar to get_toggles, invoked by 'y' key
  2411. */
  2412.  
  2413. int get_toggles2()
  2414. {
  2415.    char far *choices[20];
  2416.    int oldhelpmode;
  2417.  
  2418.    struct fullscreenvalues uvalues[25];
  2419.    int i, j, k;
  2420.  
  2421.    int old_rotate_lo,old_rotate_hi;
  2422.    int old_usr_distest,old_distestwidth;
  2423.    double old_potparam[3],old_inversion[3];
  2424.  
  2425.    ENTER_OVLY(OVLY_PROMPTS);
  2426.  
  2427.    /* fill up the choices (and previous values) arrays */
  2428.    k = -1;
  2429.  
  2430.    LOADCHOICES("Look for finite attractor (0=no,>0=yes,<0=phase)");
  2431.    uvalues[k].type = 'i';
  2432.    uvalues[k].uval.ch.val = finattract;
  2433.  
  2434.    LOADCHOICES("Potential Max Color (0 means off)");
  2435.    uvalues[k].type = 'i';
  2436.    uvalues[k].uval.ival = old_potparam[0] = potparam[0];
  2437.  
  2438.    LOADCHOICES("          Slope");
  2439.    uvalues[k].type = 'd';
  2440.    uvalues[k].uval.dval = old_potparam[1] = potparam[1];
  2441.  
  2442.    LOADCHOICES("          Bailout");
  2443.    uvalues[k].type = 'i';
  2444.    uvalues[k].uval.ival = old_potparam[2] = potparam[2];
  2445.  
  2446.    LOADCHOICES("          16 bit values");
  2447.    uvalues[k].type = 'y';
  2448.    uvalues[k].uval.ch.val = pot16bit;
  2449.  
  2450.    LOADCHOICES("Distance Estimator (0=off, <0=edge, >0=on):");
  2451.    uvalues[k].type = 'i';
  2452.    uvalues[k].uval.ival = old_usr_distest = usr_distest;
  2453.  
  2454.    LOADCHOICES("          width factor:");
  2455.    uvalues[k].type = 'i';
  2456.    uvalues[k].uval.ival = old_distestwidth = distestwidth;
  2457.  
  2458.  
  2459.  
  2460.    LOADCHOICES("Inversion radius or \"auto\" (0 means off)");
  2461.    LOADCHOICES("          center X coordinate or \"auto\"");
  2462.    LOADCHOICES("          center Y coordinate or \"auto\"");
  2463.    k = k - 3;
  2464.    for (i= 0; i < 3; i++) {
  2465.       uvalues[++k].type = 's';
  2466.       if ((old_inversion[i] = inversion[i]) == AUTOINVERT)
  2467.      sprintf(uvalues[k].uval.sval,"auto");
  2468.       else
  2469.      sprintf(uvalues[k].uval.sval,"%g",inversion[i]);
  2470.       }
  2471.    LOADCHOICES("  (use fixed radius & center when zooming)");
  2472.    uvalues[k].type = '*';
  2473.  
  2474.    LOADCHOICES("Color cycling from color (0 ... 254)");
  2475.    uvalues[k].type = 'i';
  2476.    uvalues[k].uval.ival = old_rotate_lo = rotate_lo;
  2477.  
  2478.    LOADCHOICES("              to   color (1 ... 255)");
  2479.    uvalues[k].type = 'i';
  2480.    uvalues[k].uval.ival = old_rotate_hi = rotate_hi;
  2481.  
  2482.    oldhelpmode = helpmode;
  2483.    helpmode = HELPYOPTS;
  2484.    i = fullscreen_prompt("       Extended Doodads\n\
  2485. (not all combinations make sense)",
  2486.      k+1,choices,uvalues,0,0,NULL);
  2487.    helpmode = oldhelpmode;
  2488.    if (i < 0) {
  2489.       EXIT_OVLY;
  2490.       return(-1);
  2491.       }
  2492.  
  2493.    /* now check out the results (*hopefully* in the same order <grin>) */
  2494.    k = -1;
  2495.    j = 0;   /* return code */
  2496.  
  2497.    if (uvalues[++k].uval.ch.val != finattract) {
  2498.       finattract = uvalues[k].uval.ch.val;
  2499.       j = 1;
  2500.       }
  2501.  
  2502.    potparam[0] = uvalues[++k].uval.ival;
  2503.    if (potparam[0] != old_potparam[0]) j = 1;
  2504.  
  2505.    potparam[1] = uvalues[++k].uval.dval;
  2506.    if (potparam[0] != 0.0 && potparam[1] != old_potparam[1]) j = 1;
  2507.  
  2508.    potparam[2] = uvalues[++k].uval.ival;
  2509.    if (potparam[0] != 0.0 && potparam[2] != old_potparam[2]) j = 1;
  2510.  
  2511.    if (uvalues[++k].uval.ch.val != pot16bit) {
  2512.       pot16bit = uvalues[k].uval.ch.val;
  2513.       if (pot16bit) { /* turned it on */
  2514.      if (potparam[0] != 0.0) j = 1;
  2515.      }
  2516.       else /* turned it off */
  2517.      if (dotmode != 11) /* ditch the disk video */
  2518.         enddisk();
  2519.      else /* keep disk video, but ditch the fraction part at end */
  2520.         disk16bit = 0;
  2521.       }
  2522.  
  2523.    ++k;
  2524.    usr_distest = (uvalues[k].uval.ival > 32000) ? 32000 : uvalues[k].uval.ival;
  2525.    if (usr_distest != old_usr_distest) j = 1;
  2526.    ++k;
  2527.    distestwidth = uvalues[k].uval.ival;
  2528.    if (usr_distest && distestwidth != old_distestwidth) j = 1;
  2529.  
  2530.    for (i = 0; i < 3; i++) {
  2531.       if (uvalues[++k].uval.sval[0] == 'a' || uvalues[k].uval.sval[0] == 'A')
  2532.      inversion[i] = AUTOINVERT;
  2533.       else
  2534.      inversion[i] = atof(uvalues[k].uval.sval);
  2535.       if (old_inversion[i] != inversion[i]
  2536.     && (i == 0 || inversion[0] != 0.0))
  2537.      j = 1;
  2538.       }
  2539.    invert = (inversion[0] == 0.0) ? 0 : 3;
  2540.    ++k;
  2541.  
  2542.    rotate_lo = uvalues[++k].uval.ival;
  2543.    rotate_hi = uvalues[++k].uval.ival;
  2544.    if (rotate_lo < 0 || rotate_hi > 255 || rotate_lo > rotate_hi) {
  2545.       rotate_lo = old_rotate_lo;
  2546.       rotate_hi = old_rotate_hi;
  2547.       }
  2548.  
  2549.    EXIT_OVLY;
  2550.    return(j);
  2551. }
  2552.  
  2553. /* --------------------------------------------------------------------- */
  2554. /*
  2555.     get_view_params() is called from FRACTINT.C whenever the 'v' key
  2556.     is pressed.  Return codes are:
  2557.     -1  routine was ESCAPEd - no need to re-generate the image.
  2558.      0  minor variable changed.  No need to re-generate the image.
  2559.      1  View changed.  Re-generate the image.
  2560. */
  2561.  
  2562. int get_view_params()
  2563. {
  2564.    char far *choices[8];
  2565.  
  2566.    int oldhelpmode;
  2567.    struct fullscreenvalues uvalues[25];
  2568.    int i, k;
  2569.    float old_viewreduction,old_aspectratio;
  2570.    int old_viewwindow,old_viewcrop,old_viewxdots,old_viewydots;
  2571.  
  2572.    ENTER_OVLY(OVLY_PROMPTS);
  2573.    stackscreen();
  2574.  
  2575.    old_viewwindow    = viewwindow;
  2576.    old_viewcrop      = viewcrop;
  2577.    old_viewreduction = viewreduction;
  2578.    old_aspectratio   = finalaspectratio;
  2579.    old_viewxdots     = viewxdots;
  2580.    old_viewydots     = viewydots;
  2581.  
  2582. get_view_restart:
  2583.    /* fill up the previous values arrays */
  2584.    k = -1;
  2585.  
  2586.    LOADCHOICES("Preview display? (no for full screen)");
  2587.    uvalues[k].type = 'y';
  2588.    uvalues[k].uval.ch.val = viewwindow;
  2589.  
  2590.    LOADCHOICES("Auto window size reduction factor");
  2591.    uvalues[k].type = 'f';
  2592.    uvalues[k].uval.dval = viewreduction;
  2593.  
  2594.    LOADCHOICES("Final media overall aspect ratio, y/x");
  2595.    uvalues[k].type = 'f';
  2596.    uvalues[k].uval.dval = finalaspectratio;
  2597.  
  2598.    LOADCHOICES("Crop starting coordinates to new aspect ratio?");
  2599.    uvalues[k].type = 'y';
  2600.    uvalues[k].uval.ch.val = viewcrop;
  2601.  
  2602.    LOADCHOICES("Explicit size x pixels (0 for auto size)");
  2603.    uvalues[k].type = 'i';
  2604.    uvalues[k].uval.ival = viewxdots;
  2605.  
  2606.    LOADCHOICES("              y pixels (0 to base on aspect ratio)");
  2607.    uvalues[k].type = 'i';
  2608.    uvalues[k].uval.ival = viewydots;
  2609.  
  2610.    LOADCHOICES("");
  2611.    uvalues[k].type = '*';
  2612.  
  2613.    LOADCHOICES("Press F4 to reset view parameters to defaults.");
  2614.    uvalues[k].type = '*';
  2615.  
  2616.    oldhelpmode = helpmode;     /* this prevents HELP from activating */
  2617.    helpmode = HELPVIEW;
  2618.    i = fullscreen_prompt("View Window Options",k+1,choices,uvalues,0,16,NULL);
  2619.    helpmode = oldhelpmode;     /* re-enable HELP */
  2620.    if (i < 0) {
  2621.       viewwindow    = old_viewwindow;
  2622.       viewcrop        = old_viewcrop;
  2623.       viewreduction = old_viewreduction;
  2624.       finalaspectratio = old_aspectratio;
  2625.       viewxdots     = old_viewxdots;
  2626.       viewydots     = old_viewydots;
  2627.       unstackscreen();
  2628.       EXIT_OVLY;
  2629.       return(-1);
  2630.       }
  2631.  
  2632.    if (i == F4) {
  2633.       viewwindow = viewxdots = viewydots = 0;
  2634.       viewreduction = 4.2;
  2635.       viewcrop = 1;
  2636.       finalaspectratio = SCREENASPECT;
  2637.       goto get_view_restart;
  2638.       }
  2639.  
  2640.    /* now check out the results (*hopefully* in the same order <grin>) */
  2641.    k = -1;
  2642.  
  2643.    viewwindow = uvalues[++k].uval.ch.val;
  2644.  
  2645.    viewreduction = uvalues[++k].uval.dval;
  2646.  
  2647.    if ((finalaspectratio = uvalues[++k].uval.dval) == 0)
  2648.       finalaspectratio = SCREENASPECT;
  2649.  
  2650.    viewcrop = uvalues[++k].uval.ch.val;
  2651.  
  2652.    viewxdots = uvalues[++k].uval.ival;
  2653.    viewydots = uvalues[++k].uval.ival;
  2654.  
  2655.    if (finalaspectratio != old_aspectratio && viewcrop)
  2656.       aspectratio_crop(old_aspectratio,finalaspectratio);
  2657.  
  2658.    i = 0;
  2659.    if (viewwindow != old_viewwindow
  2660.       || (viewwindow
  2661.      && (  viewreduction != old_viewreduction
  2662.         || finalaspectratio != old_aspectratio
  2663.         || viewxdots != old_viewxdots
  2664.         || (viewydots != old_viewydots && viewxdots) ) ) )
  2665.       i = 1;
  2666.  
  2667.    unstackscreen();
  2668.    EXIT_OVLY;
  2669.    return(i);
  2670. }
  2671.  
  2672. /*
  2673.     get_cmd_string() is called from FRACTINT.C whenever the 'g' key
  2674.     is pressed.  Return codes are:
  2675.     -1  routine was ESCAPEd - no need to re-generate the image.
  2676.      0  parameter changed, no need to regenerate
  2677.     >0  parameter changed, regenerate
  2678. */
  2679.  
  2680. int get_cmd_string()
  2681. {
  2682.    int oldhelpmode;
  2683.    int i;
  2684.    char cmdbuf[61];
  2685.  
  2686.    ENTER_OVLY(OVLY_PROMPTS);
  2687.  
  2688.    oldhelpmode = helpmode;
  2689.    helpmode = HELPCOMMANDS;
  2690.    cmdbuf[0] = 0;
  2691.    i = field_prompt(0,"Enter command string to use.",NULL,cmdbuf,60,NULL);
  2692.    helpmode = oldhelpmode;
  2693.    if (i >= 0 && cmdbuf[0] != 0)
  2694.        i = cmdarg(cmdbuf, 2);
  2695.  
  2696.    EXIT_OVLY;
  2697.    return(i);
  2698. }
  2699.  
  2700.  
  2701. /* --------------------------------------------------------------------- */
  2702.  
  2703. int Distribution = 30, Offset = 0, Slope = 25;
  2704. long con;
  2705.  
  2706. static char far sf1[] = {"Star Density in Pixels per Star"};
  2707. static char far sf2[] = {"Percent Clumpiness"};
  2708. static char far sf3[] = {"Ratio of Dim stars to Bright"};
  2709. static char far *starfield_prompts[] = {sf1,sf2,sf3};
  2710.  
  2711. static double starfield_values[4] = {
  2712.     30.0,100.0,5.0,0.0
  2713.     };
  2714.  
  2715. int starfield(void)
  2716. {
  2717.    static char StarMap[] = "altern.map";
  2718.    int c;
  2719.  
  2720.    if (starfield_values[0] <   1.0) starfield_values[0] =   1.0;
  2721.    if (starfield_values[0] > 100.0) starfield_values[0] = 100.0;
  2722.    if (starfield_values[1] <   1.0) starfield_values[1] =   1.0;
  2723.    if (starfield_values[1] > 100.0) starfield_values[1] = 100.0;
  2724.    if (starfield_values[2] <   1.0) starfield_values[2] =   1.0;
  2725.    if (starfield_values[2] > 100.0) starfield_values[2] = 100.0;
  2726.  
  2727.    Distribution = (int)(starfield_values[0]);
  2728.    con    = (long)(((starfield_values[1]) / 100.0) * (1L << 16));
  2729.    Slope = (int)(starfield_values[2]);
  2730.  
  2731.    if (ValidateLuts(StarMap) != 0) {
  2732.       static char far msg[]={"Unable to load ALTERN.MAP"};
  2733.       stopmsg(0,msg);
  2734.  
  2735.       return(-1);
  2736.       }
  2737.    spindac(0,1);         /* load it, but don't spin */
  2738.  
  2739.    for(row = 0; row < ydots; row++) {
  2740.       for(col = 0; col < xdots; col++) {
  2741.      if(keypressed()) {
  2742.         buzzer(1);
  2743.         return(1);
  2744.         }
  2745.      c = getcolor(col, row);
  2746.          if(c == inside)
  2747.             c = colors-1;
  2748.      putcolor(col, row, GausianNumber(c, colors));
  2749.       }
  2750.    }
  2751.    buzzer(0);
  2752.    return(0);
  2753. }
  2754.  
  2755. int get_starfield_params(void) {
  2756.    struct fullscreenvalues uvalues[3];
  2757.    int oldhelpmode, status;
  2758.    int i;
  2759.  
  2760.    ENTER_OVLY(OVLY_PROMPTS);
  2761.  
  2762.    if(colors < 255) {
  2763.       static char far msg[]={"starfield requires 256 color mode"};
  2764.       stopmsg(0,msg);
  2765.  
  2766.       EXIT_OVLY;
  2767.       return(-1);
  2768.    }
  2769.    for (i = 0; i < 3; i++) {
  2770.       uvalues[i].uval.dval = starfield_values[i];
  2771.       uvalues[i].type = 'f';
  2772.    }
  2773.    stackscreen();
  2774.    oldhelpmode = helpmode;
  2775.    helpmode = HELPSTARFLD;
  2776.    i = fullscreen_prompt("Starfield Parameters",
  2777.              3,starfield_prompts,uvalues,0,0,NULL);
  2778.    helpmode = oldhelpmode;
  2779.    if (i < 0) {
  2780.       unstackscreen();
  2781.       EXIT_OVLY;
  2782.       return(-1);
  2783.       }
  2784.    unstackscreen();
  2785.  
  2786.    for (i = 0; i < 3; i++)
  2787.       starfield_values[i] = uvalues[i].uval.dval;
  2788.  
  2789.    EXIT_OVLY;
  2790.    return(0);
  2791. }
  2792.  
  2793. /* --------------------------------------------------------------------- */
  2794.  
  2795. int get_commands()        /* execute commands from file */
  2796. {
  2797.    int ret;
  2798.    FILE *parmfile;
  2799.    long point;
  2800.    int oldhelpmode;
  2801.    ENTER_OVLY(OVLY_PROMPTS);
  2802.    ret = 0;
  2803.    oldhelpmode = helpmode;
  2804.    helpmode = HELPPARMFILE;
  2805.    if ((point = get_file_entry(GETPARM,"Parameter Set",
  2806.                    commandmask,CommandFile,CommandName)) >= 0
  2807.      && (parmfile = fopen(CommandFile,"rb"))) {
  2808.       fseek(parmfile,point,SEEK_SET);
  2809.       ret = load_commands(parmfile);
  2810.       }
  2811.    helpmode = oldhelpmode;
  2812.    EXIT_OVLY;
  2813.    return(ret);
  2814. }
  2815.  
  2816. /* --------------------------------------------------------------------- */
  2817.  
  2818. void goodbye()            /* we done.  Bail out */
  2819. {
  2820.    static char far goodbyemessage[]={"   Thank You for using FRACTINT"};
  2821.    extern BYTE exitmode;
  2822.    extern int mode7text;
  2823.    extern int made_dsktemp;
  2824. #ifndef XFRACT
  2825.    union REGS r;
  2826. #endif
  2827.  
  2828. #ifdef WINFRACT
  2829.    return;
  2830. #endif
  2831.  
  2832.    setvideotext();
  2833. #ifdef XFRACT
  2834.    UnixDone();
  2835.    printf("\n\n\n%s\n",goodbyemessage); /* printf takes far pointer */
  2836. #else
  2837.    r.h.al = (mode7text == 0) ? exitmode : 7;
  2838.    r.h.ah = 0;
  2839.    int86(0x10, &r, &r);
  2840.    printf("\n\n\n%Fs\n",goodbyemessage); /* printf takes far pointer */
  2841. #endif
  2842.    movecursor(6,0);
  2843.    discardgraphics(); /* if any emm/xmm tied up there, release it */
  2844.    stopslideshow();
  2845.    if (made_dsktemp)
  2846.       remove("FRACTINT.DSK");
  2847.    end_help();
  2848.    exit(0);
  2849. }
  2850.  
  2851.  
  2852. /* --------------------------------------------------------------------- */
  2853.  
  2854. #ifdef XFRACT
  2855. static char searchdir[FILE_MAX_DIR];
  2856. static char searchname[FILE_MAX_PATH];
  2857. static char searchext[FILE_MAX_EXT];
  2858. static DIR *currdir = NULL;
  2859. #endif
  2860. static int  findfirst(char *path)       /* Find 1st file (or subdir) meeting path/filespec */
  2861. {
  2862. #ifndef XFRACT
  2863.      union REGS regs;
  2864.      regs.h.ah = 0x1A;           /* Set DTA to filedata */
  2865.      regs.x.dx = (unsigned)&DTA;
  2866.      intdos(®s, ®s);
  2867.      regs.h.ah = 0x4E;           /* Find 1st file meeting path */
  2868.      regs.x.dx = (unsigned)path;
  2869.      regs.x.cx = FILEATTR;
  2870.      intdos(®s, ®s);
  2871.      return(regs.x.ax);        /* Return error code */
  2872. #else
  2873.      if (currdir != NULL) {
  2874.          closedir(currdir);
  2875.          currdir = NULL;
  2876.      }
  2877.      splitpath(path,NULL,searchdir,searchname,searchext);
  2878.      if (searchdir[0]=='\0') {
  2879.          currdir = opendir(".");
  2880.      } else {
  2881.          currdir = opendir(searchdir);
  2882.      }
  2883.      if (currdir==NULL) {
  2884.          return -1;
  2885.      } else {
  2886.          return findnext();
  2887.      }
  2888. #endif
  2889. }
  2890.  
  2891. static int  findnext()        /* Find next file (or subdir) meeting above path/filespec */
  2892. {
  2893. #ifndef XFRACT
  2894.      union REGS regs;
  2895.      regs.h.ah = 0x4F;           /* Find next file meeting path */
  2896.      regs.x.dx = (unsigned)&DTA;
  2897.      intdos(®s, ®s);
  2898.      return(regs.x.ax);
  2899. #else
  2900. #ifdef DIRENT
  2901.      struct dirent *dirEntry;
  2902. #else
  2903.      struct direct *dirEntry;
  2904. #endif
  2905.      struct stat sbuf;
  2906.      char thisname[FILE_MAX_PATH];
  2907.      char tmpname[FILE_MAX_PATH];
  2908.      char thisext[FILE_MAX_EXT];
  2909.      while (1) {
  2910.          dirEntry = readdir(currdir);
  2911.          if (dirEntry == NULL) {
  2912.              closedir(currdir);
  2913.              currdir = NULL;
  2914.              return -1;
  2915.          } else if (dirEntry->d_ino != 0) {
  2916.              splitpath(dirEntry->d_name,NULL,NULL,thisname,thisext);
  2917.              if ((searchname[0]=='*' || strcmp(searchname,thisname)==0) &&
  2918.                      (searchext[0]=='*' || strcmp(searchext,thisext)==0)) {
  2919.                  strncpy(DTA.filename,dirEntry->d_name,20);
  2920.                  DTA.filename[20]=='\0';
  2921.                  strcpy(tmpname,searchdir);
  2922.                  strcat(tmpname,"/");
  2923.                  strcat(tmpname,dirEntry->d_name);
  2924.                  stat(tmpname,&sbuf);
  2925.                  if ((sbuf.st_mode&S_IFMT)==S_IFREG) {
  2926.                      DTA.attribute = 0;
  2927.                  } else if ((sbuf.st_mode&S_IFMT)==S_IFDIR) {
  2928.                      DTA.attribute = SUBDIR;
  2929.                  } else {
  2930.                      continue;
  2931.                  }
  2932.                  DTA.size = sbuf.st_size;
  2933.                  return 0;
  2934.              }
  2935.          }
  2936.      }
  2937. #endif
  2938. }
  2939.  
  2940. static int lccompare(VOIDCONSTPTR arg1, VOIDCONSTPTR arg2) /* for qsort */
  2941. {
  2942.    return(strncasecmp(*((char **)arg1),*((char **)arg2),40));
  2943. }
  2944.  
  2945.  
  2946. static char *masks[] = {"*.pot","*.gif"};
  2947. static int speedstate;
  2948.  
  2949. int getafilename(char *hdg,char *template,char *flname)
  2950. {
  2951.    int masklen;
  2952.    char filename[13];
  2953.    char speedstr[81];
  2954.    char tmpmask[FILE_MAX_PATH];   /* used to locate next file in list */
  2955.    static int numtemplates = 1;
  2956.    int i,j;
  2957.    int out;
  2958.    int retried;
  2959.    struct CHOICE
  2960.    {
  2961.       char name[13];
  2962.       char type;
  2963.    }
  2964.    *choices[MAXNUMFILES];
  2965.    int attributes[MAXNUMFILES];
  2966.    int filecount;   /* how many files */
  2967.    int dircount;    /* how many directories */
  2968.    int notroot;     /* not the root directory */
  2969.  
  2970.    char drive[FILE_MAX_DRIVE];
  2971.    char dir[FILE_MAX_DIR];
  2972.    char fname[FILE_MAX_FNAME];
  2973.    char ext[FILE_MAX_EXT];
  2974.  
  2975.    ENTER_OVLY(OVLY_PROMPTS);
  2976.  
  2977.    /* steal existing array for "choices" */
  2978.    choices[0] = (struct CHOICE *)boxy;
  2979.    attributes[0] = 1;
  2980.    for(i=1;i<MAXNUMFILES;i++)
  2981.    {
  2982.       choices[i] = choices[i-1] + 1;
  2983.       attributes[i] = 1;
  2984.    }
  2985.  
  2986. restart:  /* return here if template or directory changes */
  2987.  
  2988.    tmpmask[0] = 0;
  2989.    if(flname[0] == 0)
  2990.       strcpy(flname,DOTSLASH);
  2991.    splitpath(flname ,drive,dir,fname,ext);
  2992.    makepath(filename,""   ,"" ,fname,ext);
  2993.    retried = 0;
  2994. retry_dir:
  2995.    if (dir[0] == 0)
  2996.       strcpy(dir,".");
  2997.    expand_dirname(dir,drive);
  2998.    makepath(tmpmask,drive,dir,"","");
  2999.    fix_dirname(tmpmask);
  3000.    if (retried == 0 && strcmp(dir,SLASH) && strcmp(dir,DOTSLASH))
  3001.    {
  3002.       tmpmask[(j = strlen(tmpmask) - 1)] = 0; /* strip trailing \ */
  3003.       if (strchr(tmpmask,'*') || strchr(tmpmask,'?')
  3004.     || findfirst(tmpmask) != 0
  3005.     || (DTA.attribute & SUBDIR) == 0)
  3006.       {
  3007.          strcpy(dir,DOTSLASH);
  3008.      ++retried;
  3009.      goto retry_dir;
  3010.       }
  3011.       tmpmask[j] = SLASHC;
  3012.    }
  3013.    if(template[0])
  3014.    {
  3015.       numtemplates = 1;
  3016.       splitpath(template,NULL,NULL,fname,ext);
  3017.    }
  3018.    else
  3019.       numtemplates = sizeof(masks)/sizeof(masks[0]);
  3020.    filecount = -1;
  3021.    dircount  = 0;
  3022.    notroot   = 0;
  3023.    j = 0;
  3024.    masklen = strlen(tmpmask);
  3025.    strcat(tmpmask,"*.*");
  3026.    out = findfirst(tmpmask);
  3027.    while(out == 0 && filecount < MAXNUMFILES)
  3028.    {
  3029.       if((DTA.attribute & SUBDIR) && strcmp(DTA.filename,"."))
  3030.       {
  3031.      strlwr(DTA.filename);
  3032.      if(strcmp(DTA.filename,".."))
  3033.             strcat(DTA.filename,SLASH);
  3034.      strncpy(choices[++filecount]->name,DTA.filename,13);
  3035.      choices[filecount]->type = 1;
  3036.      dircount++;
  3037.      if(strcmp(DTA.filename,"..")==0)
  3038.         notroot = 1;
  3039.       }
  3040.       out = findnext();
  3041.    }
  3042.    tmpmask[masklen] = 0;
  3043.    if(template[0])
  3044.       makepath(tmpmask,drive,dir,fname,ext);
  3045.    do
  3046.    {
  3047.       if(numtemplates > 1)
  3048.      strcpy(&(tmpmask[masklen]),masks[j]);
  3049.       out = findfirst(tmpmask);
  3050.       while(out == 0 && filecount < MAXNUMFILES)
  3051.       {
  3052.      if(!(DTA.attribute & SUBDIR))
  3053.      {
  3054.         strlwr(DTA.filename);
  3055.         strncpy(choices[++filecount]->name,DTA.filename,13);
  3056.         choices[filecount]->type = 0;
  3057.      }
  3058.      out = findnext();
  3059.       }
  3060.    }
  3061.    while (++j < numtemplates);
  3062.    if (++filecount == 0)
  3063.    {
  3064.       strcpy(choices[filecount]->name,"*nofiles*");
  3065.       choices[filecount]->type = 0;
  3066.       ++filecount;
  3067.    }
  3068.    qsort(choices,filecount,sizeof(char *),lccompare); /* sort type list */
  3069.    if(notroot == 0 && dir[0] && dir[0] != SLASHC) /* must be in root directory */
  3070.    {
  3071.       splitpath(tmpmask,drive,dir,fname,ext);
  3072.       strcpy(dir,SLASH);
  3073.       makepath(tmpmask,drive,dir,fname,ext);
  3074.    }
  3075.    if(numtemplates > 1)
  3076.       strcat(tmpmask," *.pot");
  3077.    strcpy(temp1,hdg);
  3078.    strcat(temp1,"\nTemplate: ");
  3079.    strcat(temp1,tmpmask);
  3080.    strcpy(speedstr,filename);
  3081.    if (speedstr[0] == 0)
  3082.    {
  3083.       for (i=0; i<filecount; i++) /* find first file */
  3084.      if (choices[i]->type == 0)
  3085.         break;
  3086.       if (i >= filecount)
  3087.      i = 0;
  3088.    }
  3089.    i = fullscreen_choice(0,temp1,NULL,NULL,
  3090.              filecount,(char **)choices,attributes,5,99,12,
  3091.              i,NULL,speedstr,filename_speedstr,NULL);
  3092.    if (i < 0)
  3093.    {
  3094.       EXIT_OVLY;
  3095.       return(-1);
  3096.    }
  3097.    if(speedstr[0] == 0 || speedstate == MATCHING)
  3098.    {
  3099.       if(choices[i]->type)
  3100.       {
  3101.      if(strcmp(choices[i]->name,"..") == 0) /* go up a directory */
  3102.      {
  3103.         if(strcmp(dir,DOTSLASH) == 0)
  3104.            strcpy(dir,DOTDOTSLASH);
  3105.         else
  3106.         {
  3107.            char *s;
  3108.            if(s = strrchr(dir,SLASHC)) /* trailing slash */
  3109.            {
  3110.           *s = 0;
  3111.           if(s = strrchr(dir,SLASHC))
  3112.              *(s+1) = 0;
  3113.            }
  3114.         }
  3115.      }
  3116.      else  /* go down a directory */
  3117.         strcat(dir,choices[i]->name);
  3118.      fix_dirname(dir);
  3119.      makepath(flname,drive,dir,"","");
  3120.      goto restart;
  3121.       }
  3122.       splitpath(choices[i]->name,NULL,NULL,fname,ext);
  3123.       makepath(flname,drive,dir,fname,ext);
  3124.    }
  3125.    else
  3126.    {
  3127.       if (speedstate == SEARCHPATH
  3128.     && strchr(speedstr,'*') == 0 && strchr(speedstr,'?') == 0
  3129.     && findfirst(speedstr) == 0
  3130.     && (DTA.attribute & SUBDIR)) /* it is a directory */
  3131.      speedstate = TEMPLATE;
  3132.       if(speedstate == TEMPLATE)
  3133.       {
  3134.      /* extract from tempstr the pathname and template information,
  3135.         being careful not to overwrite drive and directory if not
  3136.         newly specified */
  3137.      char drive1[FILE_MAX_DRIVE];
  3138.      char dir1[FILE_MAX_DIR];
  3139.      char fname1[FILE_MAX_FNAME];
  3140.      char ext1[FILE_MAX_EXT];
  3141.      splitpath(speedstr,drive1,dir1,fname1,ext1);
  3142.      if(drive1[0])
  3143.         strcpy(drive,drive1);
  3144.      if(dir1[0])
  3145.         strcpy(dir,dir1);
  3146.      makepath(flname,drive,dir,fname1,ext1);
  3147.      if(strchr(fname1,'*') || strchr(fname1,'?') ||
  3148.          strchr(ext1  ,'*') || strchr(ext1  ,'?'))
  3149.         makepath(template,"","",fname1,ext1);
  3150.      else if(isadirectory(flname))
  3151.         fix_dirname(flname);
  3152.      goto restart;
  3153.       }
  3154.       else /* speedstate == SEARCHPATH */
  3155.       {
  3156.      char fullpath[80];
  3157.       /* if (strchr(speedstr,'.') == NULL)
  3158.         strcat(speedstr,".gif"); */
  3159.      findpath(speedstr,fullpath);
  3160.      if(fullpath[0])
  3161.         strcpy(flname,fullpath);
  3162.      else
  3163.      {  /* failed, make diagnostic useful: */
  3164.         strcpy(flname,speedstr);
  3165.         if (strchr(speedstr,SLASHC) == NULL)
  3166.         {
  3167.            splitpath(speedstr,NULL,NULL,fname,ext);
  3168.            makepath(flname,drive,dir,fname,ext);
  3169.         }
  3170.      }
  3171.       }
  3172.    }
  3173.    EXIT_OVLY;
  3174.    return(0);
  3175. }
  3176.  
  3177. static int filename_speedstr(int row, int col, int vid,
  3178.                  char *speedstring, int speed_match)
  3179. {
  3180.    extern char speed_prompt[];
  3181.    char *prompt;
  3182.    if ( strchr(speedstring,':')
  3183.      || strchr(speedstring,'*') || strchr(speedstring,'*')
  3184.      || strchr(speedstring,'?')) {
  3185.       speedstate = TEMPLATE;  /* template */
  3186.       prompt = "File Template";
  3187.       }
  3188.    else if (speed_match) {
  3189.       speedstate = SEARCHPATH; /* does not match list */
  3190.       prompt = "Search Path for";
  3191.       }
  3192.    else {
  3193.       speedstate = MATCHING;
  3194.       prompt = speed_prompt;
  3195.       }
  3196.    putstring(row,col,vid,prompt);
  3197.    return(strlen(prompt));
  3198. }
  3199.  
  3200. static int isadirectory(char *s)
  3201. {
  3202.    if(strchr(s,'*') || strchr(s,'?'))
  3203.       return(0); /* for my purposes, not a directory */
  3204.    if(findfirst(s) != 0) /* couldn't find it */
  3205.    {
  3206.       /* any better ideas?? */
  3207.       if(strchr(s,SLASHC)) /* we'll guess it is a directory */
  3208.      return(1);
  3209.       else
  3210.      return(0);  /* no slashes - we'll guess it's a file */
  3211.    }
  3212.    else if(DTA.attribute & SUBDIR)
  3213.       return(1);   /* we're SURE it's a directory */
  3214.    else
  3215.       return(0);
  3216. }
  3217.  
  3218.  
  3219. #ifndef XFRACT    /* This routine moved to unix.c so we can use it in hc.c */
  3220. int splitpath(char *template,char *drive,char *dir,char *fname,char *ext)
  3221. {
  3222.    int length;
  3223.    int len;
  3224.    int offset;
  3225.    char *tmp;
  3226.  
  3227.    if(drive)
  3228.       drive[0] = 0;
  3229.    if(dir)
  3230.       dir[0]   = 0;
  3231.    if(fname)
  3232.       fname[0] = 0;
  3233.    if(ext)
  3234.       ext[0]   = 0;
  3235.  
  3236.    if((length = strlen(template)) == 0)
  3237.       return(0);
  3238.    offset = 0;
  3239.  
  3240.    /* get drive */
  3241.    if(length >= 2)
  3242.       if(template[1] == ':')
  3243.       {
  3244.      if(drive)
  3245.      {
  3246.         drive[0] = template[offset++];
  3247.         drive[1] = template[offset++];
  3248.         drive[2] = 0;
  3249.      }
  3250.      else
  3251.      {
  3252.         offset++;
  3253.         offset++;
  3254.      }
  3255.       }
  3256.  
  3257.    /* get dir */
  3258.    if(offset < length)
  3259.    {
  3260.       tmp = strrchr(template,SLASHC);
  3261.       if(tmp)
  3262.       {
  3263.      tmp++;  /* first character after slash */
  3264.      len = tmp - &template[offset];
  3265.      if(len >=0 && len < 80 && dir)
  3266.         strncpy(dir,&template[offset],len);
  3267.      if(len < 80 && dir)
  3268.         dir[len] = 0;
  3269.      offset += len;
  3270.       }
  3271.    }
  3272.    else
  3273.       return(0);
  3274.  
  3275.    /* get fname */
  3276.    if(offset < length)
  3277.    {
  3278.       tmp = strrchr(template,'.');
  3279.       if(tmp < strrchr(template,SLASHC) || tmp < strrchr(template,':'))
  3280.      tmp = 0; /* in this case the '.' must be a directory */
  3281.       if(tmp)
  3282.       {
  3283.      tmp++; /* first character past "." */
  3284.      len = tmp - &template[offset];
  3285.      if((len > 0) && (offset+len < length) && fname)
  3286.      {
  3287.         strncpy(fname,&template[offset],len);
  3288.         fname[len] = 0;
  3289.      }
  3290.      offset += len;
  3291.      if((offset < length) && ext)
  3292.         strcpy(ext,&template[offset]);
  3293.       }
  3294.       else if((offset < length) && fname)
  3295.      strcpy(fname,&template[offset]);
  3296.    }
  3297.    return(0);
  3298. }
  3299. #endif
  3300.  
  3301. static makepath(char *template,char *drive,char *dir,char *fname,char *ext)
  3302. {
  3303. #ifndef XFRACT
  3304.    strcpy(template,drive);
  3305.    strcat(template,dir);
  3306. #else
  3307.    strcpy(template,dir);
  3308. #endif
  3309.    strcat(template,fname);
  3310.    strcat(template,ext);
  3311.    return(0);
  3312. }
  3313.  
  3314.  
  3315. /* fix up directory names */
  3316. static void fix_dirname(char *dirname)
  3317. {
  3318.    int length;
  3319.    /* scrub white space from end for safety */
  3320.    length = strlen(dirname); /* index of last character */
  3321.    while (--length >= 0 && isspace(dirname[length])) { }
  3322.    dirname[++length] = 0;
  3323.    /* make sure dirname ends with a slash */
  3324.    if(length == 0 || dirname[length-1] != SLASHC)
  3325.       strcat(dirname,SLASH);
  3326. }
  3327.  
  3328. static int expand_dirname(char *dirname,char *drive)
  3329. {
  3330.    fix_dirname(dirname);
  3331.    if (dirname[0] != SLASHC) {
  3332.       char buf[81],curdir[81];
  3333. #ifndef XFRACT
  3334.       union REGS regs;
  3335.       struct SREGS sregs;
  3336.       curdir[0] = 0;
  3337.       regs.h.ah = 0x47; /* get current directory */
  3338.       regs.h.dl = 0;
  3339.       if (drive[0] && drive[0] != ' ')
  3340.      regs.h.dl = tolower(drive[0])-'a'+1;
  3341.       regs.x.si = (unsigned int) &curdir[0];
  3342.       segread(&sregs);
  3343.       intdosx(®s, ®s, &sregs);
  3344. #else
  3345.       getwd(curdir);
  3346. #endif
  3347.       strcat(curdir,SLASH);
  3348.       while (strncmp(dirname,DOTSLASH,2) == 0) {
  3349.      strcpy(buf,&dirname[2]);
  3350.      strcpy(dirname,buf);
  3351.      }
  3352.       while (strncmp(dirname,DOTDOTSLASH,3) == 0) {
  3353.      char *s;
  3354.      curdir[strlen(curdir)-1] = 0; /* strip trailing slash */
  3355.      if (s = strrchr(curdir,SLASHC))
  3356.         *s = 0;
  3357.      strcat(curdir,SLASH);
  3358.      strcpy(buf,&dirname[3]);
  3359.      strcpy(dirname,buf);
  3360.      }
  3361.       strcpy(buf,dirname);
  3362.       dirname[0] = 0;
  3363.       if (curdir[0] != SLASHC)
  3364.      strcpy(dirname,SLASH);
  3365.       strcat(dirname,curdir);
  3366.       strcat(dirname,buf);
  3367.       }
  3368.    return(0);
  3369. }
  3370.  
  3371. #define LOADPROMPTS(X)     {\
  3372.    static char far tmp[] = { X };\
  3373.    prompts[++nump]= tmp;\
  3374.    }
  3375.  
  3376. static int get_corners()
  3377. {
  3378.    struct fullscreenvalues values[15];
  3379.    char far *prompts[15];
  3380.    static char far xprompt[]={"          X"};
  3381.    static char far yprompt[]={"          Y"};
  3382.    static char far zprompt[]={"          Z"};
  3383.    int i,nump,prompt_ret;
  3384.    int cmag,transp3d;
  3385.    double Xctr,Yctr,Mag;
  3386.    BYTE ousemag;
  3387.    double oxxmin,oxxmax,oyymin,oyymax,oxx3rd,oyy3rd;
  3388.    double ozzmin,ozzmax,ottmin,ottmax;
  3389.    /* note that hdg[15] is used for non-transparent heading: */
  3390.    static char hdg[]={"Transparent 3d Image Coordinates"};
  3391.    int oldhelpmode;
  3392.  
  3393.    transp3d = (Transparent3D && fractalspecific[fractype].orbitcalc == Formula);
  3394.    oldhelpmode = helpmode;
  3395.    ousemag = usemag;
  3396.    oxxmin = xxmin; oxxmax = xxmax;
  3397.    oyymin = yymin; oyymax = yymax;
  3398.    oxx3rd = xx3rd; oyy3rd = yy3rd;
  3399.    ozzmin = zzmin; ozzmax = zzmax;
  3400.    ottmin = ttmin; ottmax = ttmax;
  3401.  
  3402. gc_loop:
  3403.    for (i = 0; i < 15; ++i)
  3404.       values[i].type = 'd'; /* most values on this screen are type d */
  3405.    cmag = (!transp3d && usemag && cvtcentermag(&Xctr, &Yctr, &Mag));
  3406.  
  3407.    nump = -1;
  3408.    if (cmag) {
  3409.       LOADPROMPTS("Center X");
  3410.       values[nump].uval.dval = Xctr;
  3411.       LOADPROMPTS("Center Y");
  3412.       values[nump].uval.dval = Yctr;
  3413.       LOADPROMPTS("Magnification");
  3414.       values[nump].uval.dval = Mag;
  3415.       LOADPROMPTS("");
  3416.       values[nump].type = '*';
  3417.       LOADPROMPTS("Press F7 to switch to \"corners\" mode");
  3418.       values[nump].type = '*';
  3419.       }
  3420.  
  3421.    else {
  3422.       LOADPROMPTS("Top-Left Corner");
  3423.       values[nump].type = '*';
  3424.       prompts[++nump] = xprompt;
  3425.       values[nump].uval.dval = xxmin;
  3426.       prompts[++nump] = yprompt;
  3427.       values[nump].uval.dval = yymax;
  3428.       if (transp3d) {
  3429.          prompts[++nump] = zprompt;
  3430.          values[nump].uval.dval = zzmin;
  3431.       }
  3432.       LOADPROMPTS("Bottom-Right Corner");
  3433.       values[nump].type = '*';
  3434.       prompts[++nump] = xprompt;
  3435.       values[nump].uval.dval = xxmax;
  3436.       prompts[++nump] = yprompt;
  3437.       values[nump].uval.dval = yymin;
  3438.       if (transp3d) {
  3439.      prompts[++nump] = zprompt;
  3440.      values[nump].uval.dval = zzmax;
  3441.      }
  3442.       if (transp3d) {
  3443.      LOADPROMPTS("Time Step");
  3444.      values[nump].type = '*';
  3445.      LOADPROMPTS("          From");
  3446.      values[nump].uval.dval = ttmin;
  3447.      LOADPROMPTS("          To");
  3448.      values[nump].uval.dval = ttmax;
  3449.      }
  3450.       else {
  3451.      if (xxmin == xx3rd && yymin == yy3rd)
  3452.         xx3rd = yy3rd = 0;
  3453.      LOADPROMPTS("Bottom-left (zeros for top-left X, bottom-right Y)");
  3454.      values[nump].type = '*';
  3455.      prompts[++nump] = xprompt;
  3456.      values[nump].uval.dval = xx3rd;
  3457.      prompts[++nump] = yprompt;
  3458.      values[nump].uval.dval = yy3rd;
  3459.      LOADPROMPTS("Press F7 to switch to \"center-mag\" mode");
  3460.      values[nump].type = '*';
  3461.      }
  3462.       }
  3463.  
  3464.    LOADPROMPTS("Press F4 to reset to type default values");
  3465.    values[nump].type = '*';
  3466.  
  3467.    oldhelpmode = helpmode;
  3468.    helpmode = HELPCOORDS;
  3469.    prompt_ret = fullscreen_prompt((transp3d) ? hdg : &hdg[15],
  3470.              nump+1, prompts, values, 0,
  3471.              (transp3d) ? 0x10 : 0x90, /* function keys */
  3472.              NULL);
  3473.    helpmode = oldhelpmode;
  3474.  
  3475.    if (prompt_ret < 0) {
  3476.       usemag = ousemag;
  3477.       xxmin = oxxmin; xxmax = oxxmax;
  3478.       yymin = oyymin; yymax = oyymax;
  3479.       xx3rd = oxx3rd; yy3rd = oyy3rd;
  3480.       zzmin = ozzmin; zzmax = ozzmax;
  3481.       ttmin = ottmin; ttmax = ottmax;
  3482.       return -1;
  3483.       }
  3484.  
  3485.    if (prompt_ret == F4) { /* reset to type defaults */
  3486.       xx3rd = xxmin = curfractalspecific->xmin;
  3487.       xxmax        = curfractalspecific->xmax;
  3488.       yy3rd = yymin = curfractalspecific->ymin;
  3489.       yymax        = curfractalspecific->ymax;
  3490.       if (viewcrop && finalaspectratio != SCREENASPECT)
  3491.      aspectratio_crop(SCREENASPECT,finalaspectratio);
  3492.       goto gc_loop;
  3493.       }
  3494.  
  3495.    if (cmag) {
  3496.       if ( values[0].uval.dval != Xctr
  3497.     || values[1].uval.dval != Yctr
  3498.     || values[2].uval.dval != Mag) {
  3499.      double radius,width;
  3500.      radius = 1.0 / values[2].uval.dval;
  3501.      width = radius * (1.0 / SCREENASPECT);
  3502.      yymax           = values[1].uval.dval + radius;
  3503.      yy3rd = yymin = values[1].uval.dval - radius;
  3504.      xxmax           = values[0].uval.dval + width;
  3505.      xx3rd = xxmin = values[0].uval.dval - width;
  3506.      }
  3507.       }
  3508.  
  3509.    else {
  3510.       nump = 1;
  3511.       xxmin = values[nump++].uval.dval;
  3512.       yymax = values[nump++].uval.dval;
  3513.       if (transp3d)
  3514.      zzmin = values[nump++].uval.dval;
  3515.       nump++;
  3516.       xxmax = values[nump++].uval.dval;
  3517.       yymin = values[nump++].uval.dval;
  3518.       if (transp3d)
  3519.      zzmax = values[nump++].uval.dval;
  3520.       nump++;
  3521.       if (transp3d) {
  3522.      ttmin = values[nump++].uval.dval;
  3523.      ttmax = values[nump++].uval.dval;
  3524.      }
  3525.       else {
  3526.      xx3rd = values[nump++].uval.dval;
  3527.      yy3rd = values[nump++].uval.dval;
  3528.      if (xx3rd == 0 && yy3rd == 0) {
  3529.         xx3rd = xxmin;
  3530.         yy3rd = yymin;
  3531.         }
  3532.      }
  3533.       }
  3534.  
  3535.    if (prompt_ret == F7) { /* toggle corners/center-mag mode */
  3536.       if (usemag == 0)
  3537.      if (cvtcentermag(&Xctr, &Yctr, &Mag) == 0)
  3538.      {
  3539.         static char far msg[] = 
  3540.            {"Corners rotated or stretched, can't use center-mag"};
  3541.         stopmsg(0,msg);
  3542.      }   
  3543.      else
  3544.         usemag = 1;
  3545.       else
  3546.      usemag = 0;
  3547.       goto gc_loop;
  3548.       }
  3549.  
  3550.    return((xxmin == oxxmin && xxmax == oxxmax
  3551.     && yymin == oyymin && yymax == oyymax
  3552.     && xx3rd == oxx3rd && yy3rd == oyy3rd
  3553.     && zzmin == ozzmin && zzmax == ozzmax
  3554.     && ttmin == ottmin && ttmax == ottmax) ? 0 : 1);
  3555. }
  3556.